HTTP/2 世界中的 WebSockets 替代方案是啥?

Posted

技术标签:

【中文标题】HTTP/2 世界中的 WebSockets 替代方案是啥?【英文标题】:What is the WebSockets alternative in the HTTP/2 world?HTTP/2 世界中的 WebSockets 替代方案是什么? 【发布时间】:2018-03-26 23:14:09 【问题描述】:

新的 HTTP/2 协议带有一些很有前途的特性。其中一些:

多路复用 - 单个 TCP 连接可用于发出多个 HTTP/2 请求并接收多个响应(到单个源) HTTP/2 服务器推送 - 向客户端发送服务器响应而不接收请求,即由服务器发起 双向连接 - HTTP/2 spec - Streams and Multiplexing:

“流”是一个独立的双向帧序列 在 HTTP/2 连接中在客户端和服务器之间进行交换。

这里解释了 HTTP/2 背后的动机HTTP/2 FAQ:

HTTP/1.1 已经为 Web 服务了超过 15 年,但它的 年龄开始显现了。

工作组的目标是 HTTP/1.x 的典型用途可以使用 HTTP/2 并看到一些好处。

所以 HTTP/2 很好,可以取代 HTTP/1.x。不幸的是,HTTP/2 does not support WebSockets。在这个问题Does HTTP/2 make websockets obsolete? 中明确表明 HTTP/2 服务器推送不是替代方案,Server-Sent Events 也不是。

现在问题是:如果我们希望通过 HTTP/2 实现 WebSockts 功能,我们应该使用什么?

【问题讨论】:

【参考方案1】:

嗯,你的时机很合适!

互联网标准草案的新版本刚刚发布:

Bootstrapping WebSockets with HTTP/2

这里有更多信息:

https://github.com/mcmanus/draft-h2ws/blob/master/README.md

您可以在此处关注其中的讨论:

https://lists.w3.org/Archives/Public/ietf-http-wg/2017OctDec/0032.html

直到这被批准,然后被浏览器和服务器实现,我会说Daniel Haxx’s post that you included in your question代表了当前状态的一个很好的总结。

【讨论】:

坦率地说,我发现协议的深度耦合令人不安。我更喜欢 Websocket 独立性(使用 ALPN),即使我需要限制身份验证阶段,所以它仅在 Websocket 连接建立后发生。【参考方案2】:

HTTP/2 协议协商的当前形式:

HTTP/2 连接以以下三种方式之一开始:

    在使用 ALPN(应用层协议协商)的加密连接 (TLS/SSL) 中。大多数浏览器都要求 HTTP/2 使用 TLS/SSL,并使用此方法建立 HTTP/2 连接。

    以明文形式,使用 HTTP/1.1 Upgrade 标头(与 Websockets 相同)。大多数浏览器都要求对 HTTP/2 使用 TLS/SSL,因此对它的支持是有限的。

    在明文中,在 HTTP/1.1 连接的开头使用特殊字符串(这可能允许明文中的 HTTP/2 服务器禁用 HTTP/1.1 支持)。有限的客户支持。

协商 Websocket 协议,现在时:

目前,协商 Websocket 连接需要 HTTP/1.1 支持并使用 HTTP/1.1 Upgrade 标头。

这通常由侦听 HTTP/1.1 和 HTTP/2 连接的同一应用程序服务器执行。支持并发(无论是基于事件的还是基于线程的)的 Web 应用程序通常与协议无关(只要保留 HTTP 语义),并且在两种协议上都运行良好。

这允许在连接建立期间使用 HTTP 数据(并可能影响 Websocket 连接状态/身份验证过程)。

一旦建立 Websocket 连接,它就完全独立于 HTTP 语义/层。

在 HTTP/2 世界中协商 Websocket 协议:

在一个 HTTP/2(仅)世界中,可能在未来一段时间内,可能有许多可能的 Websocket 协议协商方法:基于 ALPN 的方法和 HTTP/2“隧道”(或“流") 方法。

ALPN 方法以牺牲升级前 (HTTP) 阶段为代价来保留协议独立性,而“流”方法以牺牲高耦合和复杂性。

ALPN 方法:

未来一种可能的方法是将 Websocket 协议简单地添加到the ALPN negotiation 表中。

目前,ALPN 用于选择(或默认为)“http/1.1”协议,Upgrade 请求由 HTTP/1.1 服务器处理。这意味着 Websocket 在协议协商期间仍然为我们提供 HTTP 头数据(同时使用它自己的 TCP/IP 连接)

未来,ALPN 可能会简单地添加“wss”作为可用选项。

使用这种方法,可以使用 TLS/SSL 层的 ALPN 扩展轻松协商 Websocket(目前使用 HTTP/1.1 Upgrade 标头,以加密和明文形式建立)。

这将使 Websocket 协议独立于 HTTP/2 协议,即使在不支持 HTTP 的情况下也可以使用它。

但是,这将带来一个缺点,即 cookie 和其他 HTTP 标头可能不再作为协议协商的一部分可用。另一个区别(好的和坏的)是这种方法需要一个单独的 TCP/IP 连接。

HTTP/2“隧道”/“流”方法

in this proposed draft 反映的另一种未来可能的方法将弃用 Websocket 协议的 HTTP/1.1 变体,转而采用 HTTP/2“流”方法。

HTTP/2“流”是 HTTP/2 实现多路复用并允许同时处理多个请求的方式。每个请求都会收到一个流编号 ID,与此请求相关的任何数据(标头、响应等)都使用相同的数字流 ID 进行标识。

在这种方法下,“Websocket”数据将包含在 HTTP/2 包装器中,并且流 ID 将用于标识“Websocket”流。

虽然这可能会带来一些好处(HTTP 标头和 cookie 可以作为 Websocket 协商的一部分提供),但也并非没有缺点。

更高的复杂性和更紧密的协议耦合只是两个例子,两者都是非常严重的失败。

结论:

在撰写本文时,使用明文 (ws) 和加密 (wss) 连接时,Websocket 连接都需要 HTTP/1.1 Upgrade 语义。

未来尚未确定,目前的升级过程(使用 HTTP/1.1)可能需要很长时间才能逐步淘汰

【讨论】:

【参考方案3】:

您的一个链接实际上只有一个答案:您可以只使用 SSE。

从语义上讲,您可以使用 websockets 或 (SSE + POST ) 实现相同的功能。粗略地说,这两种技术解决不同用例的观点是围绕“这种语法更适合这个”。

目前正在努力将类似于 websockets 的东西移植到 HTTP/2,但除非这些技术能够带来新的用例或效率,否则我认为没有意义。

【讨论】:

我已经检查过了,但它看起来更像是一个 hack(解决方法)。他们说 HTTP/2 将解决问题而不是制造问题。 :) SSE 不如 Websockets 受欢迎是有原因的...尽管 SSE 具有按时间顺序排列的资历(它在 Websockets 之前可用),但它并不受社区工具的支持。任何一天我都会选择 Websockets 而不是 SSE……但也许只有我一个人。 您很好地概述了@Myst 下面的优缺点,谢谢。 “社区工具”到底是什么意思? 当我提到“社区工具”时,我想到了使用 SSE 的库(即 Ruby gems / nom 包)和服务器。与基于 SSE 的方法相比,应用程序服务器和库似乎都更喜欢 Websockets 方法。 SSE 是长轮询的完美简化,允许在一次轮询中发送多条消息……但它不是多路复用的,无法为接收到的数据发送 ACK,并且它缺少 Websockets 提供的灵活性。无论如何,只是我的 2 美分。

以上是关于HTTP/2 世界中的 WebSockets 替代方案是啥?的主要内容,如果未能解决你的问题,请参考以下文章

WCF - 使用 NetHttpBinding(WebSockets) 或替代双工绑定发送 JSON

HTTP/2 或 Websockets 用于低延迟客户端到服务器消息

解读 JavaScript 之深入探索 WebSockets 和 HTTP/2

我可以将 HTML5 WebSockets 用于通常使用 AJAX 完成的任务吗?

How Javascript works (Javascript工作原理) 深入理解 WebSockets 和带有 SSE 机制的HTTP/2 以及正确的使用姿势

是否可以将 Websockets/Socket.IO 与蜂窝数据/4g 一起使用?