1. 程式人生 > >用雙十一的故事串起碎片的網路協議(中)

用雙十一的故事串起碎片的網路協議(中)

本文來自網易雲社群

作者:劉超

上一節我們講到,手機App經過了一個複雜的過程,終於拿到了電商網站的SLB的IP地址,是不是該下單了?

別忙,俗話說的好,買東西要貨比三家。大部分客戶在購物之前要看很多商品圖片,比來比去,最後好不容易才下決心,點了下單按鈕。下單按鈕一按,就要開始建立連線。建立連線這個過程也挺複雜的,最終還要經過層層封裝,才構建出一個完整的網路包。今天我們就來看這個過程。

4. 購物之前看圖片,靜態資源CDN

客戶想要在購物網站買一件東西的時候,一般是先去詳情頁看看圖片,是不是想買的那一款。

我們部署電商應用的時候,一般會把靜態資源儲存在兩個地方,一個是接入層nginx後面的varnish快取裡面,一般是靜態頁面;對於比較大的、不經常更新的靜態圖片,會儲存在物件儲存裡面。這兩個地方的靜態資源都會配置CDN,將資源下發到邊緣節點。

配置了CDN之後,權威DNS伺服器上,會為靜態資源設定一個CNAME別名,指向另外一個域名cdn.com,返回給本地DNS伺服器。

當本地DNS伺服器拿到這個新的域名時,需要繼續解析這個新的域名。這個時候,再訪問的時候就不是原來的權威DNS伺服器了,而是 cdn.com 的權威DNS伺服器。這是CDN自己的權威DNS伺服器。

在這個伺服器上,還是會設定一個CNAME,指向另外一個域名,也即CDN網路的全域性負載均衡器。

本地DNS伺服器去請求CDN的全域性負載均衡器解析域名,全域性負載均衡器會為使用者選擇一臺合適的快取伺服器提供服務,將IP返回給客戶端,客戶端去訪問這個邊緣節點,下載資源。快取伺服器響應使用者請求,將使用者所需內容傳送到使用者終端。

如果這臺快取伺服器上並沒有使用者想要的內容,那麼這臺伺服器就要向它的上一級快取伺服器請求內容,直至追溯到網站的源伺服器,將內容拉到本地。

有關CDN,請參考《CDN:你去小賣部取過快遞麼?》

5. 看上寶貝點下單,雙方開始建連線

當你瀏覽了很多圖片,發現實在喜歡某個商品,於是決定下單購買。

電商網站會對下單的情況提供RESTful的下單介面,而對於下單這種需要保密的操作,需要通過HTTPS協議進行請求。

在所有這些操作之前,首先要做的事情是建立連線。

HTTPS協議是基於TCP協議的,因而要先建立TCP的連線。在這個例子中,TCP的連線是從手機上的App和負載均衡器SLB之間的。

儘管中間要經過很多的路由器和交換機,但是TCP的連線是端到端的。TCP這一層和更上層的HTTPS無法看到中間的包的過程。儘管建立連線的時候,所有的包都逃不過在這些路由器和交換機之間的轉發,轉發的細節我們放到那個下單請求的傳送過程中詳細解讀,這裡只看端到端的行為。

對於TCP連線來講,需要通過三次握手建立連線,為了維護這個連線,雙方都需要在TCP層維護一個連線的狀態機。

一開始,客戶端和服務端都處於CLOSED狀態。服務端先是主動監聽某個埠,處於LISTEN狀態。然後客戶端主動發起連線SYN,之後處於SYN-SENT狀態。服務端收到發起的連線,返回SYN,並且ACK客戶端的SYN,之後處於SYN-RCVD狀態。

客戶端收到服務端傳送的SYN和ACK之後,傳送ACK的ACK,之後處於ESTABLISHED狀態。這是因為,它一發一收成功了。服務端收到ACK的ACK之後,處於ESTABLISHED狀態,因為它的一發一收也成功了。

當TCP層的連線建立完畢之後,接下來輪到HTTPS層建立連線了,在HTTPS的交換過程中,TCP層始終處於ESTABLISHED。

對於HTTPS,客戶端會發送Client Hello訊息到伺服器,用明文傳輸TLS版本資訊、加密套件候選列表、壓縮演算法候選列表等資訊。另外,還會有一個隨機數,在協商對稱金鑰的時候使用。

然後,伺服器會返回Server Hello訊息,告訴客戶端,伺服器選擇使用的協議版本、加密套件、壓縮演算法等。這也有一個隨機數,用於後續的金鑰協商。

然後,伺服器會給你一個伺服器端的證書,然後說:“Server Hello Done,我這裡就這些資訊了。”

客戶端當然不相信這個證書,於是你從自己信任的CA倉庫中,拿CA的證書裡面的公鑰去解密電商網站的證書。如果能夠成功,則說明電商網站是可信的。這個過程中,你可能會不斷往上追溯CA、CA的CA、CA的CA的CA,反正直到一個授信的CA,就可以了。

證書驗證完畢之後,覺得這個服務端是可信的,於是客戶端計算產生隨機數字Pre-master,傳送Client Key Exchange,用證書中的公鑰加密,再發送給伺服器,伺服器可以通過私鑰解密出來。

接下來,無論是客戶端還是伺服器,都有了三個隨機數,分別是:自己的、對端的,以及剛生成的Pre-Master隨機數。通過這三個隨機數,可以在客戶端和伺服器產生相同的對稱金鑰。

有了對稱金鑰,客戶端就可以說:“Change Cipher Spec,咱們以後都採用協商的通訊金鑰和加密演算法進行加密通訊了。”

然後客戶端傳送一個Encrypted Handshake Message,將已經商定好的引數等,採用協商金鑰進行加密,傳送給伺服器用於資料與握手驗證。

同樣,伺服器也可以傳送Change Cipher Spec,說:“沒問題,咱們以後都採用協商的通訊金鑰和加密演算法進行加密通訊了”,並且也傳送Encrypted Handshake Message的訊息試試。

當雙方握手結束之後,就可以通過對稱金鑰進行加密傳輸了。

真正的下單請求封裝成網路包的傳送過程,我們先放一放,我們來接著講這個網路包的故事。

有關TCP協議,參考《TCP協議(上):因性惡而複雜,先惡後善反輕鬆》和《TCP協議(下):西行必定多妖孽,恆心智慧消磨難》

有關HTTP協議,參考《HTTP協議:看個新聞原來這麼麻煩》,有關HTTPS協議參考《HTTPS協議:點外賣的過程原來這麼複雜》

有關RESTful API,參考《基於JSON的RESTful介面協議:我不關心過程,請給我結果》

6. 傳送下單請求網路包,西行需要出閘道器

當客戶端和服務端之間建立了連線後,接下來就要傳送下單請求的網路包了。

在使用者層傳送的是HTTP的網路包,因為服務端提供的是RESTful API,因而HTTP層傳送的就是一個請求。