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 编辑过 |
关键字查询
相关文章
正在查询... |