Logo GH

WebSockets и SSE

1)簡而言之: 什麼以及為什麼

WebSocket(WS/WSS)是HTTP連接到全雙工通道的升級。適用於聊天、現場遊戲、協作、雙向遙測。
Server-Sent Events(SSE)是從服務器到瀏覽器的單向流(MIME 「text/event-stream」)。非常適合股票代碼,通知,報價,任務進度。客戶端-「EventSource」。

選擇規則:
  • 需要從客戶端WebSocket實時(通常是大量)→輸入。
  • 僅從服務器進行推送更新、兼容性和簡單性→ SSE更為重要。

2)網絡和協議

2.1運輸和互操作性

WebSocket:以HTTP'GET……Upgrade: websocket` (HTTP/1.1).可以使用RFC 8441 (CONNECT+':protocol=websocket'), HTTP/2支持取決於代理。在TLS (WSS)之上運行-必須在銷售中運行。
SSE:流式傳輸的常規HTTP長響應(「200 OK」)。穿過HTTP/1很好。1/2/3,與CDN/代理兼容(除非切斷長連接)。

2.2 個代理/平衡器/CDN

檢查:支持長壽命連接,idla和taymout, sticky會話(如果狀態在主機上)。
對於WS:啟用「proxy_read_timeout」、「upgrade」-sagil、per連接極限。
對於SSE:確保代理不會緩沖響應(否則客戶端不會及時看到事件)。

3)消息模型和流量控制

WebSocket:幀文本或二進制;有「ping/pong」,但沒有內置的背景信息-在應用程序上實現(隊列,窗口,下降策略)。
SSE:文本事件(UTF-8);內置的客戶端能夠以延遲的方式進行偵測;服務器可以設置「retry:」。有「id:」和標題「Last-Event-ID」可以從正確的位置恢復。

Backpressure(一般實踐):
  • 將傳出的per客戶端消息配額。
  • 限制未排隊的事件;溢出-丟棄低優先級/聚合。
  • 對於WS:在應用程序級別使用「滑動窗口」和ACK模式。

4)連接可靠性

4.1檢測和keepalive

WS:每N秒發送「ping」;Taymout斷裂-帶有指數倒數+搖桿的重新連接。
SSE:schlet「註釋」服務器':\n'作為心跳以防止連接被視為idle;客戶會重新連線。

4.2流恢復

WS:保持留言/序列,並在重新連接後請求三角洲。
SSE:對於每個事件使用'id:'和查詢中的'Last-Event-ID'-服務器跳過事件。

5)認證和授權

請求URL (WS)中的JWT Bearer不安全(日誌泄漏)。使用「Secure」、「HttpOnly」和「SameSite」標誌的標題(通過主HTTP handshake)或cookie。
mTLS(尤其是B2B)以及簽名(HMAC)在初始請求之上是可能的。
對於具有cookie的SSE,請記住有關CORS(「訪問控制-Allow-Origin」,「Allow-Credentials」)的信息。

令牌輪換:不要打斷流。傳輸「即將到期」→客戶端將重新連接新令牌。

6)數據格式和壓縮

WebSocket:小心打開永久退款(CPU);避免壓縮已經壓縮的格式(Proto、Avro)。二進制付費比JSON更經濟。
SSE:這是文本;對於大型數據,將鏈接發送到REST/gRPC資源或chunk文件;SSE傳輸gzip-適當,但要註意代理/CDN中的緩沖。

7)縮放和粉絲out

7.1水平縮放

讓應用程序在重新啟動時保持靜止。連接的狀態在前層;數據來自經紀人。
如果有本地隊列,則需要使用sticky(會議/用戶哈希)。
理想是無狀態的前面:節點僅復用訂閱;事件來自一般的pub/sub。

7.2 Pub/Sub和經紀人

對於廣泛的粉絲外出,請使用Kafka/NATS/Redis Streams。
「Fanout Gateway」層訂閱拓撲並通過WS/SSE向客戶噴槍。
應用路由密鑰(例如「userId」,「matchId」)來平衡指節之間的負載。

8)生產合金

8.1 NGINX — WebSocket

nginx map $http_upgrade $connection_upgrade { default upgrade; '' close; }

server {
listen 443 ssl http2;
server_name ws. example. com;

location /ws {
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_http_version 1. 1;
proxy_read_timeout 75s; # increase for long sessions proxy_send_timeout 15s;
proxy_pass http://ws-backend;
}
}

8.2 NGINX-SSE(必須禁用緩沖)

nginx location /events {
proxy_http_version 1. 1;
proxy_set_header Connection "";
proxy_buffering off; # is critical for proxy_cache off threads;
chunked_transfer_encoding on;
proxy_read_timeout 60m;
proxy_pass http://sse-backend;
}

8.3 Kubernetes (Ingress Annotations, NGINX Ingress)

yaml metadata:
annotations:
nginx. ingress. kubernetes. io/proxy-read-timeout: "3600"
nginx. ingress. kubernetes. io/proxy-send-timeout: "3600"
nginx. ingress. kubernetes. io/enable-websocket: "true"
nginx. ingress. kubernetes. io/proxy-buffering: "off"  # для SSE

9)代碼示例

9.1 SSE客戶端(瀏覽器)

js const es = new EventSource("/events? channel=odds", { withCredentials: true });

es. addEventListener("message", (e) => {
const data = JSON. parse(e. data);
renderOdds(data);
});

es. addEventListener("error", () => {
//EventSource will reconnect itself; can be shown spinner
});

9.2 SSE服務器(代碼。js/Express)

js app. get('/events', (req, res) => {
res. writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive',
});
res. write ('retry: 3000\n\n') ;//3s backoff to client

const sub = subscribe(req. query. channel, (event) => {
res. write(`id: ${event. id}\n`);
res. write(`event: message\n`);
res. write(`data: ${JSON. stringify(event. payload)}\n\n`);
});

req. on('close', () => sub. unsubscribe());
});

9.3 WebSocket客戶端(瀏覽器)

js const ws = new WebSocket("wss://ws. example. com/ws");
ws. onopen = () => ws. send(JSON. stringify({ type: "join", room: "chat-1" }));
ws. onmessage = (m) => handle(JSON. parse(m. data));
ws. onclose = () => scheduleReconnect();

10)安全和限制

按連接和按用戶限制:限制傳入消息的頻率(WS)和傳出流速度(WS/SSE)。
按連接壽命和總流量計算的Quota。

Message size limit и max messages/sec.

Handshake階段的WAF/機器人過濾器;防連接引導(許多短連接)。
tenant/namespace隔離:單獨的資源池。

11)可觀察性

度量標準:
  • `connections_active`, `connections_new_total`, `bytes_in/out`,
  • `messages_in/out_total`, `dropped_messages_total`,
  • `reconnects_total`, `latency_delivery_ms{p50,p95,p99}`.
  • Logs:IP/UA,userId/tenantId,關閉原因(「close_code」),持續時間。
  • 跟蹤:將事件鏈接到源命令(相關ID);對於WS,在蹦床上使用「虛擬」間諜。

12)操作細微差別

TLS終端更接近客戶端(CDN/edge)。
在脫落時主動旋轉化合物(graceful):給標記「重新連接」。
在鑰匙上縫合以均勻分配「熱」通道。
已故訂戶的狀態快照(snapshot+delta)。
最後一個值緩存(SSE特別)-對於冷客戶端很有用。

13)反模式

通過SSE或JSON通過WS流式傳輸大型二元件-使用HTTP下載和消息中的鏈接。
僅在連接時授權,在長時間內不進行筆試。
不需要的全球僵局→失衡和「熱」腳趾。
斷開的Taymauts/Lands →懸停的連接器會吞噬池。
SSE 代理/CDN緩沖→「實時」變為延遲分鐘。
缺少sequence/offset →客戶機在重新連接後會失去數據完整性。

14)實施支票

  • 選擇了以下模型:WS(雙向)或SSE(單向)。
  • 定制taymauts、keepalive和reconnect (backoff+jitter)。
  • 由sequence/offset和(用於SSE)「id」/「Last-Event-ID」設計。
  • 定義了限制:尺寸/速度/連接/配額,國防部保護。
  • Config代理/收據:升級,proxy_buffering關(SSE), read/send timeouts。
  • 縮放:pub/sub-broker, fan out-gateway, sticky只在需要時。
  • 身份驗證:令牌安全傳輸,無懸崖旋轉。
  • 可觀察性:度量,標誌,軌跡;dashbords和alertes。
  • 發布計劃:graceful-drein連接,向客戶端發出有關串聯的信號。
  • Game Days:網絡懸崖,腳趾下降,經紀人過熱,RTT長。

15) FAQ

可以通過CDN緩存SSE嗎?

通常不是:它是個性化的線程。對於公共頻道-可以使用短的TTL和chunked傳送,但很容易倒入「真實時間」。

WebSocket是否在HTTP/2/3之上運行?

瀏覽器WS從HTTP/1開始。1-upgrade;有RFC 8441 for h2,在代理/服務器中需要單獨支持。H3-運動;對於h3流媒體,有WebTransport,但它不同的API。

gRPC vs WS瀏覽器?

純瀏覽器不說gRPC;需要通過Envoy的gRPC-Web。對於交互式UI,WS+REST通常更簡單。

16)結果

WebSocket-當需要實時對話框和緊湊的雙向通道時。
SSE-當需要從服務器到客戶端的簡單可靠的推送時,最小的復雜性和自動重新連接。
銷售成功是正確的計時和限制,從offset恢復,pub/sub-fan out,正確的代理設置和清晰的可觀察性。

Contact

與我們聯繫

如有任何問題或支援需求,歡迎隨時聯絡我們。我們隨時樂意提供協助!

Telegram
@Gamble_GC
開始整合

Email 為 必填。Telegram 或 WhatsApp 為 選填

您的姓名 選填
Email 選填
主旨 選填
訊息內容 選填
Telegram 選填
@
若您填寫 Telegram,我們將在 Email 之外,同步於 Telegram 回覆您。
WhatsApp 選填
格式:國碼 + 電話號碼(例如:+886XXXXXXXXX)。

按下此按鈕即表示您同意我們處理您的資料。