每個開發人員都應該知道的WebSockets知識

葡萄城技術團隊發表於2021-02-05

轉載請註明出處:葡萄城官網,葡萄城為開發者提供專業的開發工具、解決方案和服務,賦能開發者。
原文出處:https://blog.bitsrc.io/deep-dive-into-websockets-e6c4c7622423

 

在Internet發展的早期,Web應用程式是圍繞由使用者互動觸發的HTTP請求而構建的。隨著技術的進步,對實時資料傳輸和雙向通訊的需求出現了。這是低延遲應用程式的要求,例如

  • 多人線上遊戲
  • 聊天應用
  • 實時更新社交供稿
  • 實時體育記分牌,體育行情自動收錄器等

解決以上應用場景的解決方案就是WebSockets,隨著它在技術領域被廣泛應用,出現了許多現成的庫加入了應用程式中。因此,這導致了許多開發人員在不瞭解其內部原理的情況下開始使用這個技術,以至在某些情況下影響程式的執行效率。

所以為了儘可能使程式執行效率更高效,在這篇文章中,我將為您介紹WebSocket的基本屬性及實現原理。

WebSockets架構

WebSockets的核心是定義了一個在客戶端和伺服器之間建立套接字連線的Web API。它允許自Web瀏覽器或伺服器從任何方向上的資料通訊。此外,與HTTP相比,它還進行了多項優化,使其更適合實時通訊的場景。

實時通訊

在HTTP請求中,瀏覽器傳送Cookie和其他頭資訊需要使用幾百個位元組,由於這陡增的資料容量,從而增加了實時通訊的額外開銷。

不過,如果使用WebSockets,資訊的尺寸很小,只有6個位元組的開銷(其中2個用於header報頭,4個用於掩碼值),因此,WebSockets更適合實時資料傳輸,尤其適合低延遲的應用場景。

WebSocket連線

開啟WebSocket連線很簡單。如果需要指定子協議,也可以使用第二個引數來完成。
// 建立一個Websocket連線
let socketConnection = new WebSocket('ws://websocket.mysite.com');

//建立一個使用子協議WebSocket連線
let socketConnection = new WebSocket('ws://websocket.mysite.com', ['soap', 'xmpp']);

建立Socket連線後,您可以向其附加事件處理程式,這樣您就可以知道連線什麼時候開啟、什麼時候接收訊息以及什麼時候出現錯誤。

// 當連線開啟時,一些資料會被髮送到伺服器上。
socketConnection.onopen = function () {
  connection.send('Hello, the socket connection is open!'); // Send a message to the server
};

// 記錄錯誤日誌
socketConnection.onerror = function (error) {
  console.log('WebSocket Error ' + error);
};

// 記錄來自伺服器的訊息
socketConnection.onmessage = function (e) {
  console.log('Server: ' + e.data);
};

連線建立後,將在WebSocket例項上觸發onopen事件。

這意味著握手的完成,從這個事件開始後,任何一方(伺服器和客戶端)都可以隨時向對方傳送資料。當WebSocket在客戶端接收資料時,將觸發OnMessage事件,OnError事件可用於錯誤處理。

這時候,你可能會有疑問,我們不是一直都在這樣做嗎,建立連線,監聽訊息。還有什麼其他內容嗎?

那麼,我們下面就一起來看看,如何能更高效執行WebSocket。對於WebSockets,我們如何處理連線非常重要,同時我們如何處理連線和連線錯誤重試也將決定通訊的總體容錯能力。

容錯連線重試

在使用WebSockets時,一個常見的問題就是連線中斷。當客戶端或伺服器沒有響應時,就會發生這種情況。為了避免由此產生的任何問題,您應該實現一種優雅地機制便於關閉套接字連線。特別在當 WebSocket 連線時間較長的情況下,需要實現不時重新整理連線(關閉並再次開啟連線)的方法,以實現流暢的通訊系統。

擴充套件連線

由於WebSocket具有持久連線的特性,因此需要高可用性,所以伺服器應該具有可伸縮性,以滿足需要時的高需求。但是,在開啟ws連線後,大部分時間它將處於空閒狀態。

那麼我們應該如何擴充套件WebSocket後端?

擴充套件WebSocket後端是一項複雜的任務,它需要持久儲存任何伺服器節點在出現故障時的連線和傳遞的訊息。此外,考慮開放連線的數量,最好實施橫向擴充套件策略。由於大多數使用者可能不經常重新連線,因此基於開放式連線來提高可伸縮性更為有意義。

資料傳輸模式

在通過WebSocket傳輸資料時,您可以考慮不同的模式。您可以直接通過WebSockets傳輸訊息,也可以向客戶端傳送通知,告知訊息的可用性。

用於傳送Web應用通知的WebSockets

傳送應用內通知是WebSockets的常見用例。WebSocket連線僅用於提醒瀏覽器有新訊息可用。

一旦使用者收到通知並訪問通知頁面,應用程式就可以傳送HTTP請求來檢索訊息內容。

所以在這種方法中,WebSocket並不傳送實際的訊息內容,而是作為一種信令機制來通知前端的通知可用性。

使用WebSocket進行實時資料傳輸

對於在實時多人遊戲或聊天應用程式,需要無延遲地傳送資料,因為總是有使用者盯著螢幕等待資料。

在此場景中,我們可以通過WebSocket連線直接傳送訊息資料,以便更快地傳遞訊息。

資料壓縮

對於WebSockets,壓縮不是經常討論的話題。但是,如果需要實時傳送大量資料,則使用壓縮方法是有用的。

但是,要使用WebSockets實現資料壓縮,客戶端和伺服器都需要在這一點上達成一致。

您知道WebSockets提供了資料壓縮擴充套件嗎?

當客戶端通過在SEC-WebSocket-Extensions頭中通告permessage-deflate擴充套件來發起協商時,伺服器必須通過在其響應中回顯來確認通告的擴充套件。

客戶端啟動:

GET /socket HTTP/1.1
Host: thirdparty.com
Origin: http://example.com
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Extensions: permessage-deflate
 
服務端響應:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Access-Control-Allow-Origin: http://example.com
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Extensions: permessage-deflate

WebSockets安全

WebSocket允許無限數量的訊息到達伺服器。這很容易讓攻擊者有權執行DoS攻擊。

因此,必須使用身份驗證機制來加強安全性。常見的用法之一是使用JWT令牌,這樣可以更快地驗證請求的簽名。

此外,使用wss而不是ws是至關重要的,這將保護通訊隧道,類似於HTTPS。

瀏覽器相容性

WebSocket與幾乎所有瀏覽器都具有良好的瀏覽器相容性。

 

此外,WebSocket還內建了跨域通訊。它允許與任何域上的任何方進行通訊。這可以通過定義伺服器可以與之通訊的域進行控制,從而提高安全性。

此外,流行的WebSockets實現(如Socket.IO(NodeJS)或SignalR(.NET))在較舊的瀏覽器中支援後退到HTTP。

結論

每當您需要客戶端和伺服器之間更好的低延遲連線時,WebSockets都是您的最佳選擇。

然而,WebSockets整合到您現有的Web基礎設施中可能會令人沮喪,因為它需要更改架構。此外,您還可以檢視Event Sourcing模式,該模式有效地使用WebSocket進行通訊。

請在下面的評論中告訴我您想知道的關於WebSockets的更多詳細資訊。您可以點選這裡檢視WebSocket連線演示。

 

 

相關文章