我面試人家的時候特別喜歡問一個問題:」請描述一下一個請求過來到響應完成都作了什麼,越詳細越好。」 對於一個高手來講,他只要回答好了這一個問題,技術面試就經過了。因此若是我要去面試,我就把這個問題的答案壓縮到40分鐘到1個小時。由於通常的技術面試都是這個時間段噠,雖然我其實很想講上兩天。哎,一看咱們部門就是作業務的。css
爲了讓人家聽懂,我通常會設置一個業務場景。好比說:如今用戶要開始上傳一個視頻。那麼業務上要通過用戶打開瀏覽器頁面,用戶點擊[選擇視頻文件]按鈕,JS端調用系統本地文件選擇器,JS端將視頻信息寫入到瀏覽器頁面,用戶點擊[開始上傳],此時開始發送請求。前端
我去哪裏都是隨身帶紙筆噠,爲了直觀,我會畫出頁面效果,還不忘補充一句:選擇完視頻,JS端是能夠獲取到視頻信息噠,如:名稱,大小。能夠根據業務須要直接在頁面上展現,用戶能夠對名稱進行編輯。mysql
那麼我就開始描述一下這個請求到響應都作了什麼啦:nginx
一 首先是關於HTTPS的面試
請求經過POST的方式通過HTTPS協議發送到服務器端。HTTPS自己並不是協議,而是標準的HTTP協議架在SSL/TLS協議之上的一種結構。因爲HTTP協議是基於TCP/IP進行通信的,因此HTTPS必須暴露IP和端口,這部分不加密。算法
HTTPS須要在服務器端生成私鑰,咱們服務器端用的RSA算法加密噠(對於有好幾個算法發明專利的我來講,面試時涉及到算法的地方是絕對不能漏掉噠)。而後建立簽名請求的證書,而後能夠去CA受權或者本身簽發證書,最後將證書配置到nginx裏。由於服務器上HTTPS是我配的,因此我會把這部分詳細的講出來。spring
HTTPS在傳輸數據前須要客戶端與服務端進行一次握手,在握手過程當中將確立雙方加密傳輸數據的密碼信息。握手的時候才用非對稱加密和HASH算法,握手後數據的傳輸才用對稱加密。sql
握手過程以下:數據庫
1. 瀏覽器將本身支持的一套加密規則發送給網站。設計模式
2. 網站從中選出一組加密算法與HASH算法,並將本身的身份信息用證書的形式發送給瀏覽器。證書裏包含了網站地址,加密公約,以及證書的頒發機構等信息。
3. 得到網站證書以後瀏覽器要作如下工做:
a) 驗證證書的合法性(盤發證書的機構是否合法,是否過時,證書中包含的網站地址是否與正在訪問的地址一致等),若是證書受信任,則瀏覽器欄裏面會顯示一個小鎖頭,不然會給出證書不受信任的提示。通常的瀏覽器對於本身簽發的證書都會給不收信息的提示。
b) 若是證書受信任,或者用戶接受了不受信任的證書,瀏覽器會生成一串隨機數的密碼,用最開始約定好的HASH方式,把握手消息取HASH值,而後用用證書中提供的公鑰加密」握手消息+握手消息HASH值」發送給服務端。
c) 服務端拿到客戶端傳來的密碼,用本身的私鑰來解密握手消息取出隨機數密碼,再用隨機數密碼解密握手消息與HASH值,並與傳過來的HASH值作對比確認是否一致。而後服務端本身也生成一個隨機密碼加密一段握手消息(握手消息+握手消息的HASH值)給客戶端。
d) 客戶端用隨機數解密並計算握手消息的HASH,若是與服務端發來的HASH一致,此時握手過程結束,以後的全部通訊數據將有以前瀏覽器和服務器生成的隨機碼生成的一個新的隨機密碼並利用對稱加密算法進行加密。利用客戶端和服務端的隨機碼來生成數據傳輸的隨機碼是爲了防止寫死的假隨機碼帶來的安全隱患,使用對稱加密是由於對稱加密的加密加密過程比非對稱快得多。
經常使用的非對稱加密算法有: RSA,DSA/DSS; 對稱加密算法有: AES,RC4,3DES; HASH算法:MD5,SHA1,SHA256。
二 而後是關於DNS的
請求會訪問咱們公司雲存儲那邊的DNS(Domain Name System, 域名系統),這是因特網上做爲域名和IP地址相互映射的一個分佈式數據庫,可以使用戶更方便的訪問互聯網,而不用去記住可以被機器直接讀取的IP數串。經過域名或主機名,最終獲得該域名或主機名對應的IP地址的過程叫作域名解析(或主機名解析)。DNS協議運行在UDP協議之上,使用端口號53。DNS會有一些策略將靜態的東西直接返回給瀏覽器,只有動態部分才繼續向後面傳遞。發生過測試人員在同一臺機器上在不一樣的瀏覽器上用不一樣用戶登陸,結果刷新頁面看到用戶變了的奇怪現象,是DNS策略形成的(不負責這一塊,不贅述)。
三 下面開始公司的7層代理
主要做用是轉發到對應的業務nginx代理,公司使用的是SLB進行流量分發,負載均衡(不負責這一塊,略過)
四 nginx反向代理和負載均衡
我有個什麼都想說明白的習慣。提到反向代理,就要先說正向代理。正向代理通常叫代理。就是請求發起人找一個代理作一件事情,真正作事情的人只認識代理不認識請求發起人。經常使用FQ,就是http中介的一種:代理。因此咱們使用FQ代理服務器鏈接上了國外的網站,但那個網站並不知道咱們在使用。
反向代理是服務提供方出一個代理,請求人只跟代理打交道。好比這裏請求只發給了nginx這個代理,後面的就是nginx本身進行處理,找到真正的業務處理服務器。若是是靜態請求,如css,js啥的,就直接轉向靜態服務器。若是是動態請求就轉向WEB應用服務器。然而不論是靜態服務器仍是WEB應用服務器都是有好幾臺服務器。Nginx按照必定的策略對請求向業務服務器進行分配,讓壓力不集中在一臺服務器,這就是負載均衡了。
Nginx除了配置實際處理業務的服務器,還能夠配置一些安全策略,好比若是一個IP在1秒內請求了100次,那麼將視爲攻擊,直接返回錯誤碼,不向後傳遞請求。還能夠配置超時等待時間,多媒體文件的容許大小等。
其實……,負載均衡在SLB代理那層已經作了,可是安全方面須要各個業務端本身處理,咱們每一個物理機基本上只提供一個服務,因此能夠直接使用80端口的
五 WEB應用服務
WEB應用服務整體採用SOA架構。分紅WEB前端,後臺服務,API服務,共同模塊和代理接口模塊。
WEB前端是返回頁面的,API服務是PC,手機各端都用到的共同接口。後臺服務經過代理接口模塊來和API服務及WEB前端服務進行通訊。代理接口裏含有傳遞消息的可序列化POJO。共同模塊含有一些公共方法。
請求根據nginx提供的IP和端口找到服務器上對應的WEB前端服務。咱們服務器上部署的是resin。咱們的WEB 服務採用的是SpringMVC框架(面試官哥哥會不會汗流滿面,終於說到正題上了)。SpringMVC的實現原理和核心思想老掉牙了,略過(面試官哥哥是否是要驚愕了,其實只想聽這個)。不過spring做爲一個久經考驗的框架,裏面用到了幾乎全部的設計模式,是應該好好總結一下的(之後專門寫一篇,此處略過,面試官哥哥是否是又該開始擦汗了)。
Resin WEB應用中除了SpringMVC還有一些細小的邏輯,如通常會配置utf8編碼器,logback監聽器,guava限流。請求通過Spring加載上下文,上下文可使用類加載,配置文件加載等多種方式(策略模式)。加載後咱們調用的只是ApplicationContext(門面模式),固然它同時也是一個Bean工廠(工廠模式)。DispatcherServlet將請求映射處處理器。我看過DispatcherServlet的源碼,在初始化策略的時候,還支持多種類型的處理器(適配器模式)。處理器要通過攔截器對請求的用戶身份等進行校驗,校驗不經過直接返回錯誤,校驗經過找到對應的controller而後就開始進行參數校驗。
校驗不成功返回錯誤碼。成功後HttpClient調用採用了Restful架構的視頻資源系統進行內容建立。建立不成夠返回錯誤碼。成功則須要在數據庫插入一條記錄。調用DUBBO後臺服務,服務的service層調用couchbase緩存取出當前記錄是否存在,不存在則調用mybatis持久層框架到mysql數據庫進行操做。操做成功後httpclient調用Restful架構的雲存儲那邊返回視頻上傳初始化參數。結果回到controller裏包裝成ModelAndView對象,再通過攔截器注入一些session參數。由於http協議是無狀態的,如今的系統又都是分佈式的,不支持session,因此每次都須要在攔截器裏將參數再塞入進去。而後原路返回響應。客戶端收到響應後斷開鏈接。由於http請求是無鏈接的。
固然處理過程當中會用到好多基於AOP的,好比調試,分析埋點,日誌。
瀏覽器收到響應裏含有的上傳初始化連接(返回結果裏帶着的)就會調用這個連接將真正的視頻介質傳進去。通過別的部門的雲存儲,雲轉碼。轉碼那邊會給我用消息隊列,咱們用的是qpidd mq採用direct的exchange發送到隊列。咱們這邊的監聽器監聽到隊列裏的消息就將消息解析存到數據庫。整體流程圖以下: