WebSocket

參考文件的這一部分涵蓋了對 Servlet 棧的支援,包括原始 WebSocket 互動的 WebSocket 訊息,透過 SockJS 進行的 WebSocket 模擬,以及透過 WebSocket 的子協議 STOMP 進行的釋出-訂閱訊息傳遞。

WebSocket 介紹

WebSocket 協議(RFC 6455)提供了一種標準化的方法,可以在單個 TCP 連線上在客戶端和伺服器之間建立全雙工、雙向通訊通道。它是一個與 HTTP 不同的 TCP 協議,但設計為在 HTTP 上工作,使用 80 和 443 埠,並允許重用現有的防火牆規則。

WebSocket 互動始於一個 HTTP 請求,該請求使用 HTTP Upgrade 頭來升級或在此處切換到 WebSocket 協議。以下示例展示了這種互動

GET /spring-websocket-portfolio/portfolio HTTP/1.1
Host: localhost:8080
Upgrade: websocket (1)
Connection: Upgrade (2)
Sec-WebSocket-Key: Uc9l9TMkWGbHFD2qnFHltg==
Sec-WebSocket-Protocol: v10.stomp, v11.stomp
Sec-WebSocket-Version: 13
Origin: https://:8080
1 Upgrade 頭。
2 使用 Upgrade 連線。

與通常的 200 狀態碼不同,支援 WebSocket 的伺服器會返回類似於以下的輸出

HTTP/1.1 101 Switching Protocols (1)
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: 1qVdfYHU9hPOl4JYYNXF623Gzn0=
Sec-WebSocket-Protocol: v10.stomp
1 協議切換

成功握手後,HTTP 升級請求底層的 TCP 套接字將保持開啟狀態,客戶端和伺服器都可以繼續傳送和接收訊息。

關於 WebSocket 工作原理的完整介紹超出了本文件的範圍。請參閱 RFC 6455、HTML5 的 WebSocket 章或 Web 上的眾多介紹和教程中的任何一個。

請注意,如果 WebSocket 伺服器執行在 Web 伺服器(例如 nginx)後面,您可能需要配置它將 WebSocket 升級請求傳遞給 WebSocket 伺服器。同樣,如果應用程式執行在雲環境中,請檢視雲提供商關於 WebSocket 支援的說明。

HTTP 對比 WebSocket

儘管 WebSocket 設計為與 HTTP 相容並以 HTTP 請求開始,但理解這兩種協議會導致截然不同的架構和應用程式程式設計模型非常重要。

在 HTTP 和 REST 中,應用程式被建模為許多 URL。要與應用程式互動,客戶端以請求-響應的方式訪問這些 URL。伺服器根據 HTTP URL、方法和頭資訊將請求路由到適當的處理程式。

相比之下,在 WebSocket 中,初始連線通常只有一個 URL。隨後,所有應用程式訊息都在同一個 TCP 連線上傳輸。這指向了一種完全不同的非同步、事件驅動的訊息傳遞架構。

WebSocket 也是一種低階傳輸協議,與 HTTP 不同,它對訊息內容沒有規定任何語義。這意味著除非客戶端和伺服器就訊息語義達成一致,否則無法路由或處理訊息。

WebSocket 客戶端和伺服器可以透過 HTTP 握手請求上的 Sec-WebSocket-Protocol 頭協商使用更高階的訊息協議(例如 STOMP)。如果沒有協商,它們需要制定自己的約定。

何時使用 WebSocket

WebSocket 可以使網頁變得動態和互動。然而,在許多情況下,AJAX 和 HTTP 流或長輪詢的組合可以提供簡單有效的解決方案。

例如,新聞、郵件和社交提要需要動態更新,但每隔幾分鐘更新一次可能完全可以接受。另一方面,協作、遊戲和金融應用需要更接近即時。

延遲本身不是決定因素。如果訊息量相對較低(例如,監控網路故障),HTTP 流或輪詢可以提供有效的解決方案。低延遲、高頻率和高容量的結合才是使用 WebSocket 的最佳場景。

還要記住,在網際網路上,您無法控制的限制性代理可能會阻止 WebSocket 互動,原因可能是它們未配置為傳遞 Upgrade 頭,或者它們關閉了看似空閒的長期連線。這意味著在防火牆內部使用 WebSocket 對於內部應用來說比面向公眾的應用更直接。