HTTP2 - 如何拥有类似 WebSocket 的功能(Keep-Alive、EventSource 等)

Posted

技术标签:

【中文标题】HTTP2 - 如何拥有类似 WebSocket 的功能(Keep-Alive、EventSource 等)【英文标题】:HTTP2 - How to have WebSocket-like functionality (Keep-Alive, EventSource, etc.) 【发布时间】:2018-05-26 13:39:04 【问题描述】:

想知道如何在 Node.js 中建立客户端和服务器之间的持久连接。

持久连接应该能够从双方来回发送请求。似乎它需要一种机制来描述每个请求,例如 \r\n 如果请求是 JSON,但如果之前已经完成,则不确定这里有什么最佳实践。想知道 web-sockets 是如何处理这个问题的。

Mozilla 说 Keep-Alive 不应该在生产中使用,所以想知道这是否仍然适用于 HTTP2。

使用EventSource,您可以接收服务器事件,但想知道是否有办法添加客户端事件以发送到服务器。

最后,我想为 WebSockets 之类的双向通信设置一个简单的设置,但我不确定 HTTP2 的最佳实践以及是否应该使用 WebSockets 来完成。我宁愿在没有 websockets 的情况下尝试这样做。

https://daniel.haxx.se/blog/2016/06/15/no-websockets-over-http2/

【问题讨论】:

为什么不使用 websockets?借助 socket.io 或 SockJS 等库,可以构建它们以支持旧平台 只是想了解它是如何工作的。 如果您要在应用程序之间而不是在 Web 浏览器上传递消息,请查看 grpc。它为您提供 http2 和类型安全的服务定义等等。 【参考方案1】:

恕我直言,我相信您错误地认为 HTTP/2 连接是特定于页面的。

实际上,HTTP/2 连接通常是浏览器范围的连接。 HTTP/2 push 不可能知道哪个页面/选项卡将使用数据(可能不止一个)。

另外,请参阅here 讨论,其中包含关于为什么 HTTP/2 不能(或不应该)用作 Websocket 替代方案的无数原因。

另一方面,如果 HTTP/2 被“承诺”并且 Websocket 不可用,那么轮询可能是一种选择。

使用 HTTP/2 轮询将比使用 HTTP/1.1 轮询更加资源友好,尽管由于额外的标头和身份验证数据,它仍然比 Websocket 推送(或轮询)昂贵得多(它也会减少安全性,但这可能是没有人真正关心的事情)。

附言

基于 HTTP/2 的 Websockets

除非 HTTP/1.1 被淘汰,否则这不是问题(事实上,恕我直言,这是故意的,而且很好)。

的确,HTTP/2 连接不能“升级”(更改)为 Websocket 连接,也不能隧道 Websocket 数据,但这绝对没有任何意义。

新的 Websocket 连接使用现有的 HTTP/1.1 升级握手,就是这样。

任何支持 Websockets 的 HTTP/2 服务器都将支持握手。

保持活动状态

Mozilla 对非标准的Keep-Alive 标头发出警告。但是,绝对推荐 HTTP/1.1 的 Connection: keep-alive 标准(这也是 HTTP/1.1 客户端的默认值)。

SSE(服务器发送事件)

SSE 早于 Websockets,它们在社区中并没有引起太大的关注,而 Websockets 被采用了。

想知道是否有办法添加客户端事件以发送到服务器

简单 - 发送 HTTP 请求。可以通过 SSE 异步接收回复。

我更喜欢 Websockets。就服务器端而言,我发现它们更易于管理和编码。

【讨论】:

Websockets 和 HTTP/2 不能很好地混合在一起,如果你想要一个 HTTP/2 上的站点并在同一个域上包含一个 websocket 连接,那就是一个问题。目前这不起作用,因此唯一的选择是暂时禁用 HTTP/2 或将 websocket 连接移动到不同的域。希望随着基于 HTTP/2 的 websockets 在正式规范的道路上顺利进行排序。 @BazzaDP ,我认为您遇到的问题是特定于服务器的。 HTTP/2 和 Websockets 可以在同一个域名上愉快地生活,使用同一个后端应用程序,完全没有问题。当应用服务器不支持 HTTP/2(而且似乎很多不支持)时,这很容易使用代理 Web 服务器来实现,例如 nginx,它使用 HTTP/1.1 将请求转发到应用服务器,也可以设置为直接响应静态文件请求。这是一种非常常见的设置,并且大多数应用程序服务器无论如何都在代理后面运行,用于负载平衡和 TLS 协商。 如果您想知道消息通过 HTTP/2 转到哪个选项卡,您可以使用流标识符,不是吗? @sudo 我不确定我是否理解您的评论。 HTTP/2 连接是浏览器范围的,它们不属于任何特定的选项卡/窗口。 AFAIK,HTTP/2 push 语义不能针对特定选项卡... ID 如何帮助解决这个问题? @sudo ,哦,谢谢你解释你的问题。答案是不。新的push(或确切地说是 PUSH_PROMISE)不包含有关“相关”流 ID 的任何信息。 The stream ID is totally new and unrelated to any previous request.

以上是关于HTTP2 - 如何拥有类似 WebSocket 的功能(Keep-Alive、EventSource 等)的主要内容,如果未能解决你的问题,请参考以下文章

HTTP2:如何实现流量控制功能?

go websocket 问题(Hijacker)

网络推送协议如何工作?

如何使用同一端口(使用码头 8)拥有具有多个上下文的 websocket

如何结合 Spring REST 和 WebSocket?

如何通过 websocket 优化发送绘图?