WebSockets

參考文件的這部分涵蓋 Servlet stack 的支援、WebSocket 訊息傳遞 (包括原始 WebSocket 互動、透過 SockJS 的 WebSocket 模擬) 以及透過 STOMP 作為 WebSocket 子協定的發布-訂閱訊息傳遞。

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://127.0.0.1:8080
1 Upgrade 標頭。
2 使用 Upgrade 連線。

具有 WebSocket 支援的伺服器,不會傳回通常的 200 狀態代碼,而是傳回類似於以下的輸出

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

成功握手後,HTTP 升級請求的底層 TCP Socket 保持開啟,以便用戶端和伺服器繼續發送和接收訊息。

完整介紹 WebSocket 的運作方式超出本文檔的範圍。請參閱 RFC 6455、HTML5 的 WebSocket 章節,或網路上眾多的簡介和教學課程。

請注意,如果 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)。在沒有該標頭的情況下,他們需要提出自己的慣例。

何時使用 WebSockets

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

例如,新聞、郵件和社群摘要需要動態更新,但每隔幾分鐘更新一次可能完全沒問題。另一方面,協作、遊戲和金融應用程式需要更接近即時。

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

另請記住,在網際網路上,您無法控制的限制性代理伺服器可能會排除 WebSocket 互動,原因可能是它們未設定為傳遞 Upgrade 標頭,或者因為它們關閉了看似閒置的長期連線。這表示在防火牆內部的內部應用程式中使用 WebSocket 比在面向公眾的應用程式中使用 WebSocket 更為直接。