服務器推送、在線遊戲和電子郵件背後的網絡協議

2023.09.05

服務器推送、在線遊戲和電子郵件背後的網絡協議


現在我們將深入探討關鍵的網絡協議及其在不同應用中的作用。重點在於理解這些協議如何塑造我們在互聯網上的通信和互動方式。

之前也聊了不少網絡協議這塊內容,現在我們將深入探討關鍵的網絡協議及其在不同應用中的作用。重點在於理解這些協議如何塑造我們在互聯網上的通信和互動方式。我們將深入研究以下領域:

WebSocket

在之前的討論中,我們研究了HTTP及其在客戶端和服務器之間的典型請求-響應交互中的作用。HTTP在大多數情況下表現良好,特別是當響應是即時的時候。然而,在服務器需要主動向客戶端推送更新的情況下,尤其是這些更新依賴於客戶端無法預測的事件(比如其他用戶的操作),HTTP可能不是最有效的方法。這是因為HTTP基本上是一種拉取(pull-based)協議,客戶端必鬚髮起所有請求。那麼,在不需要客戶端預測和請求每個更新的情況下,如何讓服務器向客戶端推送數據呢?通常有四種處理這種推送型通信的方法,如下圖所示。

1. 短輪詢(Short polling)

這是最基本的方法。在這種方法中,客戶端,通常是運行在我們的瀏覽器中的Web應用程序,會不斷向服務器發送HTTP請求。想像這樣的場景:我們登錄到一個Web應用程序,並被要求用智能手機掃描一個二維碼。這個二維碼通常用於某個特定的操作,比如認證或啟動某個過程。Web應用程序不知道我們何時會掃描二維碼。因此,它會每1-2秒向服務器發送一次請求,以檢查二維碼的狀態。一旦我們用智能手機掃描了二維碼,服務器會識別掃描,然後在Web應用程序的下一個檢查請求中,將更新後的狀態發送回來。這樣,我們在掃描二維碼後將在接下來的1-2秒內得到響應。由於這種頻繁的檢查,我們將這種方法稱為“短輪詢”。

這種方法有兩個問題:

  • 它發送大量的HTTP請求,佔用帶寬並增加服務器負載。
  • 在最壞的情況下,我們可能要等待長達2秒才能收到響應,導致明顯的延遲。

2. 長輪詢(Long polling)

長輪詢通過設置較長的HTTP請求超時時間來解決短輪詢的問題。可以這樣理解:我們將超時時間調整為30秒。如果我們在這個時間段內掃描了二維碼,服務器將立即發送響應。這種方法顯著減少了HTTP請求的數量。

然而,長輪詢並非沒有挑戰。即使長輪詢減少了請求的數量,但每個開放的請求仍然需要與服務器保持連接。如果有許多客戶端,這可能對服務器資源造成壓力。

3. WebSocket

短輪詢和長輪詢適用於簡單的任務,比如掃描二維碼。但對於復雜、數據量大且需要實時交互的任務,比如在線遊戲,需要一種更高效的解決方案- 這就是WebSocket。

TCP本質上允許雙向數據流,使客戶端和服務器能夠同時相互發送數據。然而,基於TCP的HTTP/1.1並未充分利用這種能力。在HTTP/1.1中,數據傳輸通常是按順序進行的- 一方發送數據,然後另一方回應。這種設計對於網頁交互足夠,但對於需要實時交互的在線遊戲等應用而言顯得不足。WebSocket是另一種基於TCP的協議,在單個連接上允許全雙工通信,填補了這個空白。稍後我們將詳細介紹。

4. SSE (Server-Sent Events)

SSE,即服務器推送事件,適用於特定的用例。當客戶端建立SSE連接時,服務器保持此連接開放以持續發送更新。這種設置非常適用於服務器需要定期向客戶端推送數據的情況,而客戶端只需接收數據,無需向服務器發送信息。典型的例子是實時股票市場數據更新。使用SSE,服務器可以在每次有更新時向客戶端推送實時數據,而無需每次更新都發送請求。值得注意的是,與WebSocket不同,SSE不支持雙向通信,因此在需要雙向交互的用例中不太適用。

如何建立WebSocket連接

要建立WebSocket連接,我們需要在HTTP頭部包含特定字段,這些字段告訴瀏覽器切換到WebSocket協議。一個隨機生成的Base64編碼密鑰(Sec-WebSocket-Key)被發送到服務器。

請求頭:

Connection: Upgrade 
Upgrade: WebSocket
Sec-WebSocket-Key: T2a6wZlAwhgQNqruZ2YUyg==
  • 1.
  • 2.
  • 3.

服務器響應頭:

HTTP/1.1 101 Switching Protocols
Sec-WebSocket-Accept: iBJKv/ALIW2DobfoA4dmr3JHBCY=
Upgrade: WebSocket
Connection: Upgrade
  • 1.
  • 2.
  • 3.
  • 4.

狀態碼101表示協議正在切換。經過這個額外的握手後,WebSocket連接建立完成,如下圖所示:

9f2ff945-1c60-4e43-9252-474e74dc4fe7_1600x1303.png

WebSocket消息

一旦HTTP升級為WebSocket,客戶端和服務器將在幀中交換數據。我們來看一下數據是什麼樣子的:

操作碼(Opcode)是一個4位字段,表示幀數據的類型。

  • “1”表示文本幀。
  • “2”表示二進制幀。
  • “8”表示關閉連接的信號。

有效負載長度可以是一個7位字段,也可以擴展為包含擴展的有效負載長度。如果這兩個長度字段都被充分利用,有效負載長度可以表示幾個TB的數據。

WebSocket適用於在線遊戲、聊天室和協作編輯應用等需要客戶端和服務器頻繁交互的場景。

RPC

RPC允許在不同服務上執行函數。從調用程序的角度來看,它似乎是在本地執行函數。下圖展示了本地過程調用和遠程過程調用之間的區別。我們可以將訂單管理和支付等模塊部署在同一進程或不同服務器上。當部署在同一進程時,這是本地函數調用。當部署在不同服務器上時,這是遠程過程調用。

為什麼我們需要RPC?難道我們不能使用HTTP在服務之間進行通信嗎?讓我們在下表中比較RPC和HTTP。

 RPC相對於HTTP的主要優勢在於它輕量級的消息格式和卓越的性能。例如,gRPC就是一個例子,它在HTTP/2上運行,由於這一點,它具有更好的性能。

接下來,我們將探討另一個重要的應用層協議- RPC(遠程過程調用)。

讓我們逐步了解gRPC的運作流程:

  • 第一步:客戶端發起一個REST調用。請求體通常以JSON格式表示。
  • 第二至四步:訂單服務(充當gRPC客戶端)接收到REST調用後,將其轉換成適當的格式,並且發起一個RPC調用給支付服務。gRPC將客戶端存根編碼成二進制格式,並將其發送到底層傳輸層。
  • 第五步:gRPC通過HTTP2將數據包發送到網絡。二進制編碼和網絡優化使得gRPC比JSON快上多達五倍。
  • 第六至八步:支付服務(充當gRPC服務器)接收到數據包後,對其進行解碼,並調用服務器應用程序。
  • 第九至十一步:服務器應用程序返回的結果被編碼並發送回傳輸層。
  • 第十二至十四步:訂單服務接收到數據包後,對其進行解碼,並將結果發送給客戶端應用程序。