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

11

新的HTTP/2协议带来了一些有前途的功能,其中包括:

  • 多路复用 - 一个TCP连接可用于发起多个HTTP/2请求并接收多个响应(到单个源)
  • HTTP/2服务器推送 - 无需接收请求即可将服务器响应发送到客户端,即由服务器启动
  • 双向连接 - HTTP/2规范 - 流和多路复用:

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

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

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

工作组的目标是,HTTP/1.x的典型用法可以使用HTTP/2并获得一些好处。

所以HTTP/2很好,并取代了HTTP/1.x。不幸的是,HTTP/2不支持WebSockets。在这个问题中 “HTTP/2是否使WebSocket过时?”清楚地表明了HTTP/2服务器推送也不是一个选择,服务器发送事件(EventSource)也不是。

现在来回答问题:如果我们想要在HTTP/2上实现WebSocket功能,我们该用什么?

3个回答

6

坦白说,我觉得协议的深度耦合令人不安。我更喜欢WebSocket独立(使用ALPN),即使需要限制身份验证阶段只能在建立WebSocket连接后进行。 - Myst

6

HTTP/2协议的当前形式:

HTTP/2连接有三种方式:

  1. 通过使用ALPN(应用层协议协商)进行加密连接(TLS/SSL)。大多数浏览器需要TLS/SSL来进行HTTP/2连接建立,因此使用此方法。

  2. 使用HTTP/1.1 Upgrade头(与Websockets相同)进行明文传输。大多数浏览器需要TLS/SSL来进行HTTP/2,因此受到支持的限制。

  3. 在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)阶段,而“流”方法则提供了HTTP预“升级”(或Connect)阶段,但代价是高度耦合和复杂性。

基于ALPN的方法:

一个可能的未来方法将简单地将Websocket协议添加到ALPN协商表中。

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

未来,ALPN可能只需添加“wss”作为可用选择。

使用这种方法,WebSocket(目前使用HTTP/1.1 Upgrade头部在加密和明文形式下建立)可以轻松通过TLS/SSL层的ALPN扩展进行协商。
这将使WebSocket协议与HTTP/2协议独立,并允许在不支持HTTP时使用。
然而,这也会带来负面影响,即cookie和其他HTTP标头可能不再作为协议协商的一部分。另一个区别(既好又坏)是这种方法需要一个单独的TCP/IP连接。
HTTP/2 "tunnel" / "stream" 方法
另一种可能的未来方法,反映在这个提案草案中,将放弃WebSocket协议的HTTP/1.1变体,采用HTTP/2 "stream"方法。
HTTP/2 "stream" 是HTTP/2实现多路复用的方式,允许多个请求同时处理。每个请求都会收到一个流号ID,该请求相关的任何数据(标头、响应等)都使用同一数字流ID进行标识。
根据这种方法,“WebSocket”数据将包含在HTTP/2封装中,并使用流ID来标识“WebSocket”流。
虽然这可能会提供一些好处(HTTP标头和cookie可以作为WebSocket协商的一部分提供),但也存在缺点。
更高的复杂性和更紧密的协议耦合只是其中两个例子,这两个问题都非常严重。
结论:
在撰写本文时,WebSocket连接需要使用HTTP/1.1 Upgrade语义,无论是使用明文(ws) 还是加密(wss)连接。
未来仍未决定,目前的升级过程(使用HTTP/1.1)可能需要很长时间才能停用。

4

你提供的链接实际上有一个答案:你可以使用SSE。

语义上,你可以通过Websockets或(SSE + POST)实现相同的功能。认为这两种技术解决不同的用例是在围绕“这个语法对于此更有效”展开无谓的争论。

目前正在进行将类似Websockets的东西移植到HTTP/2的工作,但除非这些技术能够实现新的用例或效率,否则我看不出它们的意义所在。


1
我已经检查过了,但它似乎更像是一个hack(解决方法)。他们说HTTP/2将解决问题而不是创造问题。 :) - Nikola Obreshkov
SSE比Websockets不太受欢迎,这是有原因的...尽管SSE在时间上更早(它比Websockets先推出),但它没有得到社区工具的支持。我会选择Websockets而不是SSE...但也许只是我个人的偏好。 - Myst
你在下面非常好地概述了优缺点,@Myst,谢谢。你所说的“社区工具”是什么意思? - dsign
当我提到“社区工具”时,我想的是库(例如Ruby gems / nom packages)和使用SSE的服务器。应用程序服务器和库似乎更喜欢Websockets方法而不是基于SSE的方法。 SSE对于长轮询是一个美丽的简化,允许在单个轮询上发送多个消息...但它不是多路复用的,没有办法发送数据接收的ACK,并且缺少Websockets提供的灵活性。无论如何,这只是我的看法。 - Myst

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接