HTTP / 2是否会使websocket过时?


268

我正在学习HTTP / 2协议。这是带有小消息帧的二进制协议。它允许通过单个TCP连接进行流多路复用。从概念上讲,它似乎与WebSockets非常相似。

是否有计划淘汰Websocket,并用某种无头HTTP / 2请求和服务器启动的推送消息替换它们?还是WebSockets可以补充HTTP / 2?


我认为已接受的答案是正确的,WebSocket仍然是Web应用程序与服务器双向通信(包括服务器推送的消息)的首选解决方案。HTTP不仅用于浏览器,而且当客户端和服务器都可以使用低级API时,它们不需要websocket。仍然大多数人将HTTP用于Web应用程序,并且大多数人担心JavaScript公开的API。如果主持人认为接受的答案应该有所不同,那么我并不反对,因为这个问题显然引起了很多观点,我的观点可能是错误的。
vbezhenar

Answers:


161

据我了解,HTTP / 2不是websocket的替代品,而是旨在标准化SPDY协议。

在HTTP / 2中,幕后使用server-push来改善客户端从浏览器的资源加载。作为开发人员,您在开发过程中并不十分在意。但是,使用Websocket,允许开发人员使用API​​,该API能够使用唯一的全双工连接来使用和推送消息。

这些不是同一回事,它们应该相互补充。


3
谢谢Guillaume的回答。但是,我想知道您(或某人)是否可以从HTTP / 2规范中添加一些参考。我从博客等中学到的内容-使用HTTP / 2可以进行真正的双向通信?
马丁·梅瑟

3
不确定HTTP / 2规范是否是提供有关HTTP / 2的起源以及它与websocket的区别的详细信息的正确位置。但是,您可以很容易地看到,通过HTTP / 2,我们正在使用双向通信: goo.gl/IJVxWS(第6和13页)
Guillaume D.

27
HTTP / 2确实是双向的,但不是对称的,这意味着只有客户端可以发送适当的请求,而服务器可以发送响应和请求承诺(推送)。在使双方在发送/接收内容方面更加“平等”的意义上,这使网络套接字有所不同。
George Antoniadis 2015年

3
IEEE的软件工程电台上有一个关于HTTP2起源的出色播客。我认为是这样的: se-radio.net/2015/07/episode-232-mark-nottingham-on-http2
Max Murphy

2
:具有完全的理由类似的答案可以此相关的文章在这里可以找到infoq.com/articles/websocket-and-http2-coexist
mantrid

151

在刚刚阅读完HTTP / 2规范之后,我认为HTTP / 2在大多数用例中确实已经过时,但并不是全部。

PUSH_PROMISE(俗称服务器推送)不是这里的问题。那只是性能优化。

浏览器中Websocket的主要用例是启用双向数据流。因此,我认为OP的问题在于HTTP / 2是否在启用浏览器中的双向流传输方面做得更好,我认为是的。

首先,它 bi-di。只需阅读streams部分的介绍:

“流”是HTTP / 2连接中客户端和服务器之间交换的独立的双向帧序列。流具有几个重要特征:

单个HTTP / 2连接可以包含多个并发打开的流,其中任一端点都可以交错多个流中的帧。

流可以单方面建立和使用,也可以由客户端或服务器共享。

可以通过任一端点关闭流。

文章像这样(在另一个答案挂钩)是错误的约HTTP / 2的这一方面。他们说这不是比迪烟。看,HTTP / 2不会发生一件事:打开连接后,服务器无法启动常规流,只能启动推送流。但是,一旦客户端通过发送请求打开流,双方就可以随时通过持久套接字发送DATA帧-完整的比迪。

这与websockets没什么不同:客户端也必须发起一个websocket升级请求,然后服务器才能发送数据。

最大的区别在于,与websocket不同,HTTP / 2定义了自己的多路复用语义:流如何获取标识符以及帧如何携带其所在流的ID。HTTP / 2还定义了用于对流进行优先级排序的流控制语义。这在比迪的大多数实际应用中都很重要。

(那篇错误的文章还说Websocket标准具有多路复用。不,它不是。要发现这一点并不难,只需打开Websocket RFC 6455并按⌘-F,然后输入“ multiplex”即可。

该协议旨在可扩展;未来的版本可能会引入其他概念,例如多路复用。

您会发现有用于Websocket多路复用的2013年扩展草案。但是我不知道哪些浏览器支持该功能。我不会尝试在该扩展程序的背面构建我的SPA webapp,尤其是在HTTP / 2出现的情况下,该支持可能永远无法到达)。

完全是多路复用,通常是每当您打开一个用于bidi的websocket(例如,为响应式更新的单页应用程序提供动力)时就必须做的事情。我很高兴它在HTTP / 2规范中,一劳永逸。

如果您想知道HTTP / 2可以做什么,只需看一下gRPC。gRPC是在HTTP / 2上实现的。请专门看一下gRPC提供的半双工和全双工流选项。(请注意,gRPC当前在浏览器中不起作用,但这实际上是因为浏览器(1)不向客户端javascript公开HTTP / 2框架,以及(2)通常不支持Trailer,后者用于gRPC规范。)

Websocket可能还在哪里?最大的是服务器->浏览器推送的二进制数据。HTTP / 2确实允许服务器->浏览器推送二进制数据,但是在浏览器JS中未公开。对于诸如推送音频和视频帧之类的应用程序,这就是使用websocket的原因。

编辑:2020年1月17日

随着时间的流逝,这个答案逐渐上升到顶部(这很好,因为这个答案或多或少是正确的)。但是,仍然偶尔有评论说,由于各种原因,它是不正确的,通常是由于PUSH_PROMISE对单个消息或有关如何实际使用面向消息的服务器的困惑->单页面应用程序中的客户端推送。而且,在浏览器中有一个用于Websocket的用例,它是服务器推送的二进制数据。对于包括JSON的文本数据,请不要使用websocket,请使用SSE。

回顾一下:HTTP / 2协议是完整的bi-di。但是,现代的网络浏览器不会将面向框架的HTTP / 2协议公开给JavaScript。不过,如果您通过HTTP / 2连接向同一源发出多个请求,那么实际上所有这些流量都将在一个连接上多路传输(这就是我们所关心的!)。

因此,如果您需要构建一个实时聊天应用程序,比如说,您需要向聊天室中所有具有开放连接的客户端广播新的聊天消息,则可以(并且应该应该)在没有websocket的情况下执行此操作。

您将使用“服务器发送的事件”来推送消息,并使用“ 提取” API来向上发送请求。服务器发送事件(SSE)是鲜为人知但广受支持的 API,它公开了面向消息的服务器到客户端流。尽管对于客户端JavaScript而言,它看起来并不像,但您的浏览器(如果支持HTTP / 2)在后台将重新使用单个TCP连接来多路复用所有这些消息。没有效率损失,实际上比websockets有所收获。需要多个流?打开多个事件源!它们会自动为您多路复用。

与Websocket握手相比,服务器发送事件除了具有更高的资源效率和更少的初始延迟外,还具有不错的属性,即它们可以自动回退并通过HTTP / 1.1进行工作。但是,当您使用HTTP / 2连接时,它们的运行情况非常好。

这是一篇很好的文章,其中包含完成反应式更新SPA 的真实示例


21
此答案与包括已接受的答案在内的其他答案部分不同,并且也是最佳答案,因为它基于直接来源。
sudo

7
我完全同意这个答案和评论。HTTP / 2是基于流的双向。
Martin Meeser

3
实际上是正确的答案,这家伙费心检查源代码和实际应用程序(grpc)
弗拉基米尔·

1
在websockets中,服务器无法开始推送任意字节,直到客户端发起websocket升级请求,然后服务器才可以随时推送。在HTTP / 2中,服务器无法开始推送字节,直到客户端启动数据连接为止,但随后它可以随时推送字节。功能上有什么区别?正如我所指出的那样,PUSH_PROMISE功能是一个红鲱鱼。这不是HTTP / 2替代Web套接字的原因。这只是次要的性能优化。它与HTTP / 2的核心无关,即双向流式传输。
masonk

1
这个答案是完全错误的。它混淆了很多方面,很容易造成混淆。但是,问题的症结在于“双向” HTTP / 2流是请求-响应驱动的(并且数量有限),而WebSockets协议是真正的基于消息的比迪协议(它不是基于请求-响应,握手阶段除外)。这是一个巨大的差异,仅通过错误阅读规范就无法弥合(因为@masonk似乎无意中完成了)。
Myst

64

我说不(Websockets还不是过时的)。

第一个也是最常被忽略的问题是HTTP / 2推送不可强制执行,并且可能被代理,路由器,其他中介程序甚至浏览器忽略

即(来自HTTP2草案):

中介可以从服务器接收推送,并选择不将其转发给客户端。换句话说,如何利用推送的信息取决于该中介。同样,中介程序可以选择向客户端进行其他推送,而无需服务器采取任何措施。

因此,HTTP / 2推送不能替代WebSockets。

同样,HTTP / 2连接会在一段时间后关闭。

标准确实指出:

HTTP / 2连接是持久的。为了获得最佳性能,期望客户端在确定不需要与服务器进行进一步通信之前(例如,当用户离开特定网页时)或在服务器关闭连接之前,不会关闭连接。

但...

鼓励服务器尽可能长时间地保持打开的连接,在必要时允许服务器终止空闲连接。当任一端点选择关闭传输层TCP连接时,终止端点应首先发送一个GOAWAY(第6.8节)帧,以便两个端点都能可靠地确定先前发送的帧是否已被处理,并能正常完成或终止任何必要的剩余任务。

即使同一连接允许在打开内容时推送内容,即使HTTP / 2解决了HTTP / 1.1的“保持活动”引入的一些性能问题,HTTP / 2连接也不会无限期保持打开状态。

网页一旦关闭,也无法重新启动HTTP / 2连接(除非我们返回到长期拉动状态)。

编辑(2017年,两年后)

HTTP / 2的实现表明,多个浏览器选项卡/窗口共享一个HTTP / 2连接,这意味着push它将永远不知道它属于哪个选项卡/窗口,从而消除了使用pushWebsockets的替代方法。

编辑(2020)

我不确定为什么人们会开始拒绝答案。如果有的话,自最初发布答案以来的几年证明,HTTP / 2不能替代WebSockets,并且并非旨在这样做。

诚然,HTTP / 2可以被用来隧道 WebSocket连接,但这些隧道连接仍然需要WebSocket协议的时候,就会实现HTTP / 2容器的行为方式。


4
WS套接字也不会永远保持打开状态。区别在于流;HTTP / 2为您提供了多个流流,这意味着服务器上的流控制是非常不同的,并且通常是无锁的。WS(作为协议)必须具有不受管制的入站处理。流控制在堆栈的更高位置实现。在安全性和服务器完整性方面,HTTP / 2比WS更好。
债券

3
@bond,我同意HTTP / 2 作为传输层具有许多优点(在许多浏览器选项卡中共享一个连接只是一个示例)。但是,它没有被设计为通信层。这是一个功能性的问题。两种协议都满足不同的需求。即ssh使用Websockets时,在浏览器上实现终端是一件轻而易举的事情。HTTP / 2会让您头疼不已,特别是如果打开了一个以上的选项卡。另外,如果浏览器(或HTTP / 2代理之一)关闭连接怎么办?客户可以假设没有新数据可用吗?我们回到了投票。
Myst

1
浏览器可以轻松关闭WS连接。任何形式的网络连接就是生命。老实说,HTTP / 2中的多路复用是过大的。该协议确实不需要它。通过打开多个流,您开始遇到TCP缓冲区限制吞吐量的问题。我同意您的观点,WS比HTTP / 2做得更好。从根本上讲,WS是需要很多高级控制才能防止用户做坏事的东西。
债券

2
引用本叔叔(蜘蛛侠)的话:“记住,能力越大,责任就越大”。是的,@ bond,您说的很对。Websockets是一种非常“原始”的协议,需要更负责任的服务器设计。是的,WS可以像HTTP / 2一样容易地关闭,但是WS支持onclose回调,因此不需要轮询。至于多路复用,我认为这是必要的,而不是选择。keep-alive失败,避免“第一线”性能下降的唯一方法是冒险复用。时间会证明
一切的

1
从服务器设计的角度来看,出站复用是一个复杂且昂贵的问题。这需要IO技师在内部进行轮询,这真是太贵了。除非您正在流式传输大文档,否则多路复用甚至无法正常工作,因为在第二个偶数变为可用且多路复用无法运行之前,请求可能已在内部进行了响应和完全缓冲。RTMP具有出站多路复用,但是只有Adobe的服务器可以执行。令人惊讶的是HTTP / 2与RTMP如此接近。
债券

39

答案是不。两者之间的目标有很大的不同。甚至还有一个用于HTTP / 2上的WebSocket的RFC,它允许您通过单个HTTP / 2 TCP管道建立多个WebSocket连接。

通过减少打开新连接的时间并允许更多的通信通道,而不会增加更多的套接字,软IRQ和缓冲区的开销,HTTP over WS上的WS将成为一种资源节约型游戏。

https://tools.ietf.org/html/draft-hirano-httpbis-websocket-over-http2-01


棒极了!是否有实现此功能的Javascript客户端有任何公开示例?我找不到任何例子。我该怎么办?这是好资源吗?undertow.io/blog/2015/04/27/An-in-depth-overview-of-HTTP2.html
RaisinBranCrunch

有谁知道上述要求的源头:1)查找标题的长度,2)字段名称的下划线?
Pim Heijden

@PimHeijden要检测HTTP / 1.x中的标头长度,需要循环遍历所有字节以寻找4个字节的结束标记。那是非常昂贵的。字段名称不区分大小写也意味着必须对字符的大写和小写版本都进行任何字段匹配。这需要了解整个字符集的大小写,以便进行检查。在2.x中,您可以假定它们是小写字母。
债券

@RaisinBranCrunch您无法通过Javascript控制任何此类操作。浏览器为您完成所有操作。
债券

@bond我目前正在将HTTP / 2与Nginx一起使用,并使用proxy_pass将Websocket连接发送到套接字服务器,但是当我有一个用户在网站中打开多个选项卡时,套接字服务器会将其视为多个连接。我假设如果HTTP / 2通过一个TCP管道多路复用连接,则服务器会将其视为一个连接。错了吗 有什么方法可以验证服务器没有进行不必要的额外连接吗?
RaisinBranCrunch

23

好吧,引用此InfoQ文章:

好吧,答案很显然是不行的,原因很简单:正如我们上面所看到的,HTTP / 2引入了服务器推送,它使服务器能够主动将资源发送到客户端缓存。但是,它不允许将数据下推到客户端应用程序本身。服务器推送仅由浏览器处理,不会弹出应用程序代码,这意味着应用程序没有API可以获取这些事件的通知。

因此,HTTP2推送确实是您的浏览器和服务器之间的东西,而Websockets确实公开了可供客户端(javascript(如果其在浏览器上运行))和应用程序代码(在服务器上运行)可用于传输实时数据的API。


5

可以通过Http / 2复用和WebSockets进行消息交换和简单的流传输(不是音频,视频流传输)。因此存在一些重叠,但是WebSocket具有完善的协议,大量的框架/ API和较少的标头开销。 这是有关该主题的不错的文章


2

HTTP / 2中将有WebSocket实现。 https://tools.ietf.org/html/rfc8441


没有,不会... WebSocket连接将通过HTTP / 2 进行隧道传输,但是HTTP / 2不会替代协议,也不会过时。
神秘

@我说过吗?
Dzintars

2
不,您没有这么说,我做到了。您写道,在HTTP / 2中将有一个WebSocket实现,由于忽略了重要的细节,恕我直言,IMHO似乎太短且有些误导。
Myst

2

到2020年4月为止,HTTP / 2并未使WebSockets过时。WebSockets优于HTTP2的最大优点是

HTTP/2 works only on Browser Level not Application Level

意味着HTTP / 2不提供任何JS API(例如WebSockets)来允许通信并将某种JSON或其他数据直接从应用程序(例如网站)传输到服务器。因此,据我所知,HTTP / 2仅在开始提供诸如WebSockets之类的API来与服务器通信时才会使WebSockets过时。直到它只是HTTP 1.1的更新和更快的版本。


2

截至今天为止。

与HTTP相比,HTTP / 2允许您维护与服务器的连接。从那里,您可以同时拥有多个数据流。目的是即使您没有客户端请求,也可以同时推送多个内容。例如,当浏览器要求输入时index.html,服务器可能还希望推送index.cssindex.js。浏览器并没有要求它,但是服务器可能会在不询问的情况下提供它,因为它可以假设您将在几秒钟内想要得到它。

这是比获得的HTTP / 1方案快index.html,解析它,发现它需要index.jsindex.css建设2个这些文件的其他请求。HTTP / 2使服务器可以推送客户端甚至不需要的数据。

在这种情况下,它与WebSocket相似,但实际上并不是设计使然。WebSocket应该允许类似于TCP连接或串行连接的双向通信。这是一个彼此通信的套接字。而且,主要区别在于您可以发送任何原始数据字节中的任意数据包,而不用HTTP协议封装。标头,路径,查询字符串的概念仅在握手期间发生,但WebSocket会打开数据流。

另一个区别是,您可以使用Javascript对WebSocket进行更精细的访问,而使用HTTP,则由浏览器处理。使用HTTP所能获得的就是XHR/中可以容纳的所有内容fetch()。这也意味着浏览器将得到截获并修改HTTP头,不你能够控制它(如:OriginCookies等)。同样,HTTP / 2能够推送的内容也会发送到浏览器。这意味着JS并不总是(如果有的话)知道事物被推送。同样,这是有道理的index.cssindex.js因为浏览器将对其进行缓存,但对于数据包则没有那么多。

确实是所有名称。HTTP代表超文本传输​​协议。我们致力于转移资产的概念。WebSocket是关于建立套接字连接的,双向二进制数据在该套接字连接中传递。


我们没有真正讨论的是SSE(服务器发送事件)。将数据推送到应用程序(JS)并不是HTTP / 2的意图,而是用于SSE的。使用HTTP / 2确实增强了SSE。但是,当重要的是数据本身而不是到达变量端点时,这并不是WebSockets的真正替代。对于使用WebSocket的每个终结点,都会创建一个新的数据流,但是使用SSE,它会在已存在的HTTP / 2会话之间共享。


这里总结了每个目标:

  • HTTP-使用一项资产响应请求
  • HTTP / 2-响应具有多个资产的请求
  • SSE-使用单向文本(UTF-8)事件流进行响应
  • WebSocket-创建双向二进制数据流
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.