HTTP/2 + SSE 能否完全替代 Websocket嗎?
當前位置:點晴教程→知識管理交流
→『 技術文檔交流 』
1. 什么是 SSE(Server-Sent Events)服務器發送事件 (SSE) 是一種標準化協議,允許 Web 服務器將數據推送到客戶端而無需使用替代機制,例如: ping、長輪詢 (Long Polling) 或 WebSocket。 ![]() 服務器發送事件(SSE)是 HTML5 公布的一種服務器向瀏覽器客戶端發起數據傳輸的技術。一旦創建了初始連接,事件流將保持打開狀態 直到客戶端關閉。該技術通過傳統的 HTTP 發送,并具有 WebSocket 缺乏的各種功能,例如:自動重新連接、 事件 ID 以及 發送任意事件 的能力。 ?? SSE 本身并沒有提供自動重連的機制,其所謂的自動重連特性是指 ` 瀏覽器自動處理與服務器的連接斷開并嘗試重新連接的過程 `。當然開發者也可以通過 `eventSource.retry = 5000` 手動重連。 SSE 就是利用服務器向客戶端聲明,接下來要發送的是流信息(streaming),會連續不斷地發送過來。這時,客戶端不會關閉連接,會一直等著服務器發過來的新的數據流,可以類比視頻流。SSE 就是利用這種機制,使用流信息向瀏覽器推送信息。其基于 HTTP 協議,目前除了 IE/Edge,其他瀏覽器都支持。 Content-Type: text/event-stream// 必須是 UTF-8 編碼的文本,流本質就是下載Cache-Control: no-cacheConnection: keep-alive 使用 SSE 可以 顯著節省便攜式設備的帶寬和電池壽命,并且可以與現有的基礎設施配合使用,因為其直接通過 HTTP 協議運行而無需像 WebSockets 那樣進行連接升級。 2.SSE 如何借力 HTTP2 補齊與 WebSocket 的短板由于 SSE 是基于 HTTP 的,其天然適配于 HTTP/2,這樣 SSE 就可以集兩者之長:HTTP/2 可以基于多路復用流形成一個高效傳輸層,同時 SSE 給應用提供了 API 使之能夠進行推送 。 ?? 流就是一個獨立的、在客戶端服務器之間的 HTTP/2 連接上雙向的幀序列,其最重要的一個特征就是 ` 單個 HTTP/2 連接可以包含多個并發開啟的流 `,其中每個端點都交錯著來自多個流的幀。 ![]() 假如應用使用 HTTP/1 傳輸,此時 NetWork 選項卡可能會有如下的輸出: ![]() 瀏覽器會并行打開多個 HTTP/1.x 連接來加速頁面加載,而 不同的瀏覽器針對同一域名并發打開的連接數量有不同的限制,基本上都會支持 6 個左右不同的連接。 為了克服這個限制,類似于 域名分片的技術就被用來將資源分布在多個域名上。這些技術(可以將其認為是非法入侵)包括 JavaScript 和 CSS 文件、圖像和資源內聯,在 HTTP/2 世界中反而適得其反。這可能是遷移到 HTTP/2 時受到的最主要的影響了,即 消除多年以來所做的優化。 當使用 HTTP/2 的時候,NetWork 中會看到瀏覽器使用單個多路復用的連接,帶來更快的加載時間。 ![]() 而 SSE 是基于 HTTP 的,這意味著使用 HTTP/2 的時候,不僅僅可以在一個 TCP 連接上交錯多個 SSE 流,同時還可以將多個 SSE 流(服務器到客戶端推送)與多個客戶端請求(客戶端到服務器)交錯。 const http2 = require('http2');const fs = require('fs');// 創建 HTTP/2 服務器const server = http2.createSecureServer({ key: fs.readFileSync('server-key.pem'), cert: fs.readFileSync('server-cert.pem')});server.on('stream', (stream, headers) => { const path = headers[':path']; const method = headers[':method']; if (path === '/events' && method === 'GET') { // 設置響應頭 stream.respond({ 'content-type': 'text/event-stream', ':status': 200 }); // 發送一條歡迎消息 stream.write(`data: Welcome! Current time is ${new Date().toISOString()}\n\n`); // 每 5 秒發送一條消息 const intervalId = setInterval(() => { stream.write(`data: Current time is ${new Date().toISOString()}\n\n`); }, 5000); // 清理工作 stream.on('close', () => { clearInterval(intervalId); }); } elseif (path === '/send-data' && method === 'POST') { // 客戶端通過 fetch('https://localhost:3000/send-data') 發送消息到服務端 let body = ''; stream.on('data', chunk => { body += chunk.toString(); }); stream.on('end', () => { console.log('Received data:', body); stream.respond({':status': 200}); stream.end(JSON.stringify({ status: 'success', data: body})); }); } else { stream.respond({':status': 404}); stream.end(); }});// 監聽端口server.listen(3000, () => { console.log('Server running at https://localhost:3000/');}); // 下面是瀏覽器連接 HTTP/2 的示例const eventSource = new EventSource('https://localhost:3000/events');// 監聽消息事件eventSource.onmessage = function(event) { const messageDiv = document.getElementById('messages'); const newMessage = document.createElement('div'); newMessage.textContent = `New message: ${event.data}`; messageDiv.appendChild(newMessage);};// 監聽連接打開事件eventSource.onopen = function(event) { console.log('Connection opened');};// 監聽錯誤事件eventSource.onerror = function(event) { if (eventSource.readyState === EventSource.CLOSED) { console.log('Connection closed'); } else { console.log('Error occurred, attempting to reconnect...'); }};// 發送 HTTP/2 請求document.getElementById('sendButton').addEventListener('click', () => { fetch('https://localhost:3000/send-data', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({message: 'Hello, server!'}) }) .then(response => response.json()) .then(data => { console.log('Response:', data); }) .catch(error => { console.error('Error:', error); });}); 比如上面的 http2 代碼示例:
有了 HTTP/2 和 SSE 就可以使用一個純 HTTP 雙向連接,加之使用簡單的 API 使應用代碼注冊多個服務器推送。 雙向能力的缺失一直是 SSE 對比 Websocket 時最主要的短板。有了 HTTP/2 就彌補了這個短板,從而為跳過 Websocket 并堅持使用基于 HTTP 的機制提供了可能。 3.HTTP/2 + SSE 能完全替代 Websocket 嗎?答案是 No,主要是 Websocket 已經被大量應用,同時在某些特定應用場景下,其底層設計致力于雙向能力,擁有較少的負載的優勢就會體現出來。假設需要在雙端之間交互大吞吐量的消息,其中上下流動的消息量大致差不多(比如,需要保持所有玩家同步的大型多人在線游戲),這種場景下 Websocket 可能會是更好的選擇。 如果考慮像是展示 實時市場新聞、市場數據、聊天應用 等場景的時候,依賴 HTTP/2 + SSE 會提供高效的雙向通信通道并保有留在 HTTP 世界的大量優勢:
因此 HTTP/2 + SSE 能否完全替代 Websocket 的結論是:
Websocket 技術可能會繼續使用,但是 SSE 和其 EventSource API 同 HTTP/2 的能力相結合可以在多數場景下達到同樣的效果,而且會更簡單。 參考資料https://zhuanlan.zhihu.com/p/37365892 https://blog.csdn.net/cnweike/article/details/116056371 https://www.infoq.com/articles/websocket-and-http2-coexist/ https://stackoverflow.com/questions/48344634/why-do-we-need-sse-when-we-have-http2-bidirectional-streaming 閱讀原文:原文鏈接 該文章在 2025/5/6 12:43:08 編輯過 |
關鍵字查詢
相關文章
正在查詢... |