通过 HTTP/2 通过 websocket 发送冗余数据实际上是免费的吗?
Is sending redundant data over websocket over HTTP/2 practically free?
我正在编写一个 Web 应用程序功能,该功能将使用 WebSocket 消息在客户端和服务器之间传输 JSON 结构。该应用程序最简单的协议是不断重复来回发送大部分冗余部分。 HTTP/2 压缩能否有效地压缩来回的单独消息中的冗余部分? 我知道这在理论上应该是可行的,但在实践中怎么样?
示例:
假设 shared_state
是一个 大部分 相同但不同消息之间不相同的字符串:
客户端连接:
ws = new WebSocket("wss://myserver.example/foo/bar");
客户端通过 WebSocket 连接发送消息:
{ command: "foo", shared_state: "...long data here..." }
服务器发送:
{ command: "bar", shared_state: "...long data here slightly modified..." }
客户端发送:
{ command: "zoo", shared_state: "...long data here slightly modified again..." }
所有这些消息都将使用单个 websocket 通过单个 HTTP/2 连接传递。
双向发送的消息会被HTTP/2压缩吗?这意味着后面的数据包可以有效地使用一些对先前在同一 HTTP/2 连接中传输的数据中已经看到的数据的引用。如果我可以继续发送共享状态而不是仅仅发送 delta 而不会在实践中导致高带宽使用,这将简化我需要实现的自定义协议。不支持HTTP/2.
的老客户不用管
我假设消息之间的差异小于 1 KB,但包括冗余部分在内的整个消息通常在 10-60 KB 范围内。
WebSocket 在 HTTP/2 上的工作方式是 WebSocket 帧在 HTTP/2 DATA
帧中作为不透明字节进行传输。
逻辑 WebSocket 连接由单个 HTTP/2 流承载,具有“无限”请求内容和“无限”响应内容,因为 DATA
帧(包含 WebSocket 帧)继续从客户端流向服务器并从服务器到客户端。
由于 WebSocket 字节由 DATA
帧承载,因此 HTTP/2 级别没有进行“压缩”。
HTTP/2 仅在 HEADERS
帧中通过 HPACK 为 HTTP headers 提供“压缩”,但 HTTP/2 上的 WebSocket 无法利用它(因为它不使用 HTTP/2 HEADERS
帧).
您的自定义协议有 key/value 对,但它是由 DATA
帧承载的 WebSocket 负载。
您将获得的唯一“压缩”是由 WebSocket 的 permessage-deflate 功能驱动的。
例如,浏览器会打开一个连接,在 HTTP/2 上建立 WebSocket(使用 WebSocket 升级期间协商的 permessage-deflate 扩展名),然后发送 WebSocket 消息。 WebSocket 消息将被压缩,压缩后的字节打包成 WebSocket 帧,WebSocket 帧打包成 HTTP/2 DATA
帧,然后通过网络发送。
如果您的 shared_state
压缩得很好,那么您就是在用网络带宽(较少的网络字节数)换取 CPU 使用(解压缩)。
如果它压缩不好,那么它可能不值得。
我建议您查看基于 WebSocket 的现有协议,可能已经有一些协议可以满足您的需求(例如,Bayeux)。
此外,请考虑不使用 JSON 作为格式,因为现在 JavaScript 支持二进制,因此您可能会更有效率(参见示例 CBOR)。
我正在编写一个 Web 应用程序功能,该功能将使用 WebSocket 消息在客户端和服务器之间传输 JSON 结构。该应用程序最简单的协议是不断重复来回发送大部分冗余部分。 HTTP/2 压缩能否有效地压缩来回的单独消息中的冗余部分? 我知道这在理论上应该是可行的,但在实践中怎么样?
示例:
假设 shared_state
是一个 大部分 相同但不同消息之间不相同的字符串:
客户端连接:
ws = new WebSocket("wss://myserver.example/foo/bar");
客户端通过 WebSocket 连接发送消息:
{ command: "foo", shared_state: "...long data here..." }
服务器发送:
{ command: "bar", shared_state: "...long data here slightly modified..." }
客户端发送:
{ command: "zoo", shared_state: "...long data here slightly modified again..." }
所有这些消息都将使用单个 websocket 通过单个 HTTP/2 连接传递。
双向发送的消息会被HTTP/2压缩吗?这意味着后面的数据包可以有效地使用一些对先前在同一 HTTP/2 连接中传输的数据中已经看到的数据的引用。如果我可以继续发送共享状态而不是仅仅发送 delta 而不会在实践中导致高带宽使用,这将简化我需要实现的自定义协议。不支持HTTP/2.
的老客户不用管我假设消息之间的差异小于 1 KB,但包括冗余部分在内的整个消息通常在 10-60 KB 范围内。
WebSocket 在 HTTP/2 上的工作方式是 WebSocket 帧在 HTTP/2 DATA
帧中作为不透明字节进行传输。
逻辑 WebSocket 连接由单个 HTTP/2 流承载,具有“无限”请求内容和“无限”响应内容,因为 DATA
帧(包含 WebSocket 帧)继续从客户端流向服务器并从服务器到客户端。
由于 WebSocket 字节由 DATA
帧承载,因此 HTTP/2 级别没有进行“压缩”。
HTTP/2 仅在 HEADERS
帧中通过 HPACK 为 HTTP headers 提供“压缩”,但 HTTP/2 上的 WebSocket 无法利用它(因为它不使用 HTTP/2 HEADERS
帧).
您的自定义协议有 key/value 对,但它是由 DATA
帧承载的 WebSocket 负载。
您将获得的唯一“压缩”是由 WebSocket 的 permessage-deflate 功能驱动的。
例如,浏览器会打开一个连接,在 HTTP/2 上建立 WebSocket(使用 WebSocket 升级期间协商的 permessage-deflate 扩展名),然后发送 WebSocket 消息。 WebSocket 消息将被压缩,压缩后的字节打包成 WebSocket 帧,WebSocket 帧打包成 HTTP/2 DATA
帧,然后通过网络发送。
如果您的 shared_state
压缩得很好,那么您就是在用网络带宽(较少的网络字节数)换取 CPU 使用(解压缩)。
如果它压缩不好,那么它可能不值得。
我建议您查看基于 WebSocket 的现有协议,可能已经有一些协议可以满足您的需求(例如,Bayeux)。
此外,请考虑不使用 JSON 作为格式,因为现在 JavaScript 支持二进制,因此您可能会更有效率(参见示例 CBOR)。