轉載請注明出處:葡萄城官網,葡萄城為開發者提供專業的開發工具、解決方案和服務,賦能開發者。
原文出處: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連接演示。