【发布时间】:2018-11-30 02:11:09
【问题描述】:
我的 Web 应用程序中要求客户端到服务器消息的延迟非常低。
我在 stackoverflow 上看到了几篇帖子,说最好使用 websockets 而不是 HTTP 来满足这个要求,但那是很久以前的事了。
在 2018 年的今天,随着 HTTP/2 的进步,这个用例还值得使用 websockets 吗?
【问题讨论】:
我的 Web 应用程序中要求客户端到服务器消息的延迟非常低。
我在 stackoverflow 上看到了几篇帖子,说最好使用 websockets 而不是 HTTP 来满足这个要求,但那是很久以前的事了。
在 2018 年的今天,随着 HTTP/2 的进步,这个用例还值得使用 websockets 吗?
【问题讨论】:
在我的 Web 应用程序中,客户端到服务器消息的延迟非常低。
我认为您想“连接”然后在 client 和 server 之间发送 低延迟消息。
HTTP/2 和 Websocket 都可以是二进制的,并且传输消息的帧具有相似的开销(几个字节),但 Websocket 必须遍历完整消息以屏蔽有效负载然后接收器必须将其反转。见What is the mask in a WebSocket frame?
此外,Websocket 原语更底层,例如要拥有多个消息流,您必须自己完成,但使用 HTTP/2 很容易完成。参考Podcast about HTTP/2。在同一个应用程序中同时使用 Websocket 和 HTTP 时,服务器代码也会变得更加复杂。
流控制在使用 HTTP/1.1 Websocket 时可能会出现问题,但它是 HTTP/2 中的内置协议功能。
这可以通过使用fetch 和response.body.getReader(); 获得ReadableStream 来有效地使用HTTP/2 完成。一篇关于浏览器 JavaScript 流的好文章:2016 - the year of web streams。
目前,在 HTTP 中从客户端向服务器发送消息的唯一方法是发送 完整请求。流式请求正文已计划但尚未由浏览器实现。有关流式请求正文,请参阅 Fetch with ReadableStream as Request Body。
【讨论】:
HTTP/2 有multiplexing,这意味着不应该有等待时间——就像在 HTTP/1 下由于每个域有 6 个连接限制。所以这意味着它可以用于你所说的低延迟连接。
但是,HTTP 仍有其他开销,例如 HTTP 标头,这可能会为小型请求添加大量不必要的额外数据,而使用 Web 套接字则不会。
此外,HTTP/2 不是全双工协议,因此只能响应请求(尽管由于服务器推送,可能会有多个响应)。你说你只需要这个来进行客户端-服务器消息传递,所以这对你来说可能不是那么重要。
支持 HTTP/2 的二进制框架层是一个全双工协议,因此理论上可能类似于 websockets,但 HTTP/2 不允许这样做 - 除非你只是拖出发送请求和响应主体来伪造它(@ 987654322@ 或 Server-Sent Events)。事实上,Websockets over HTTP/2 已获批准,通过在 HTTP/2 数据帧中包装 websockets 消息,将允许 HTTP/2 二进制格式用于 websockets。这还有一个额外的优势,即还允许在同一连接上发送常规 HTTP 消息。在撰写本文时,它还没有在任何浏览器中可用(尽管有 version 65 of FireFox 和 Chrome has started an implementation)。在那之前,Websockets 会恢复到 HTTP/1.1。
另请参阅此问题和答案:Does HTTP/2 make websockets obsolete?
【讨论】:
这将取决于您的客户和您的要求。如果您确定您的客户端不会关闭 HTTP/2 的底层 TLS 连接(即使一段时间未使用),则发送消息/请求的延迟可能类似于持久的 websocket 连接。如果客户端在空闲一段时间后关闭连接,需要建立新的 TLS 连接,情况会更糟。
在浏览器作为客户端的情况下,您知道 Web 套接字连接将是持久的,并且对 HTTP 连接一无所知。也许您可以通过向同一服务器上的 SSE 端点发出虚拟请求并保持连接来强制浏览器保持连接,但这是一种解决方法。
除了建立连接外,两种协议都有不同类型的开销(流控制和流标头与掩码),并且很可能只能根据实际应用需求来估计影响。
【讨论】: