HTTP/2是否使websockets过时了?

vbe*_*nar 229 websocket http2

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

是否有计划废弃websockets并用某种无头HTTP/2请求和服务器启动的推送消息替换它们?或者WebSockets是否会补充HTTP/2?

Gui*_* D. 139

据我所知,HTTP/2不是websocket的替代品,但旨在标准化SPDY协议.

在HTTP/2中,在场景后面使用server-push来改善客户端从浏览器加载资源.作为开发人员,您在开发过程中并不真正关心它.但是,使用Websocket,开发人员可以使用API​​,该API能够使用唯一的全双工连接来使用和推送消息.

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

  • HTTP/2确实是双向的但不是对称的,这意味着只有客户端才能发送正确的请求,服务器可以发送响应并请求promises(推送).这使得websockets在双方在允许发送/接收的方面更"平等"的意义上是不同的. (17认同)
  • 不确定HTTP/2规范是否提供有关HTTP/2起源及其与websocket的不同之处的详细信息.但是,您可以很容易地看到,使用HTTP/2,我们正在使用双向通信:http://goo.gl/IJVxWS(第6页和第13页) (3认同)
  • 谢谢Guillaume的回答.但是我想知道你(或某人)是否可以从HTTP/2规范中添加一些引用.我从博客中读到的内容等等 - 使用HTTP/2进行真正的双向通信? (2认同)
  • IEEE的软件工程广播中有一个关于HTTP2起源的优秀播客.我想是这样的:http://www.se-radio.net/2015/07/episode-232-mark-nottingham-on-http2/ (2认同)
  • 类似的答案与完整的理由可以在这篇InfoQ文章中找到:https://www.infoq.com/articles/websocket-and-http2-coexist (2认同)

mas*_*onk 117

在完成阅读HTTP/2规范之后,我认为HTTP/2确实在大多数用例中废弃了websockets,但可能并非全部.

PUSH_PROMISE(通俗地称为服务器推送)不是这里的问题.这只是性能优化.

浏览器中Websockets的主要用例是启用双向数据流.因此,我认为OP的问题在于HTTP/2是否能更好地在浏览器中启用双向流,我认为是的,确实如此.

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

"流"是在HTTP/2连接内在客户端和服务器之间交换的独立的双向帧序列.流有几个重要特征:

单个HTTP/2连接可以包含多个并发打开的流,其中任一端点交叉来自多个流的帧.

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

任何端点都可以关闭流.

文章像这样(在另一个答案链接)只是错HTTP/2的这一方面.他们说这不是比迪.看,HTTP/2有一件事是不可能发生的:连接打开后,服务器无法启动常规流,只能推送流.但是一旦客户端通过发送请求打开流,双方都可以随时发送数据帧.如果您只想要一个流,客户端只需发送"获取所有数据"请求,并在会话的剩余时间内收听它.这与websockets没什么不同:客户端必须在服务器发送数据之前发起websocket升级请求.在HTTP/2和Websocket中,一旦客户端通过请求数据来填充泵,双方都可以随时在持久套接字上发送帧 - 完全双向.HTTP/2的这种"只有一个流"的可能性只是一个退化的基本情况,如果忽略或者不想使用HTTP/2实现的某些额外功能(如流复用),您将得到什么.

多路复用很重要.与websockets不同,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)没有将HTTP/2帧暴露给客户端javascript,并且(2)通常不支持预告片,它们用于gRPC规范.)

websockets哪里可以有位置?如果你不需要任何 HTTP/2规范的额外位(这是一个巨大的,复杂的规范),那么websockets也许更好.挥手解决实施难度,我相信遵守websocket协议总是比HTTP/2计算成本更低 - HTTP/2只需要你做更多的事情.

框架的大小非常可比.与HTTP/2固定的9相比,Websocket帧略小,每帧2-14字节的开销.因为websocket选择了可变长度的头,它可以编码更大的帧(每帧最多2 ^ 64-1位vs每帧HTTP/2 2 ^ 24-1比特).因此,如果你需要一个插座来吸收没有很多仪式的东西,比如,我不知道,也许是视频帧,那么websockets可能仍然有意义.对于大多数用例,特别是与网页相关的事情,我认为HTTP/2看起来像是前进的方向.

  • 此答案与包括已接受的答案在内的其他答案部分不同,并且也是最佳答案,因为它基于直接来源。 (9认同)
  • 这个答案根本就是错误的。它混淆了很多方面,很容易让人混淆。然而,问题的关键在于“bidi”HTTP/2 流是**请求-响应**驱动的(并且数量有限),而 WebSockets 协议是真正基于**消息**的 bidi 协议(它不是基于请求-响应的,握手阶段除外)。这是一个**巨大的**差异,不能仅仅通过误读规范来弥补(就像 @masonk 无意中所做的那样)。 (7认同)
  • 我完全同意这个答案和评论。HTTP / 2是基于流的双向。 (4认同)
  • 实际上正确的答案,这家伙费心检查来源和现实世界的应用程序(grpc) (3认同)
  • 忽略 PUSH_PROMISE(服务器推送)很有帮助。它会分散我们对 HTTP/2 的理解,而且很少被使用,更很少被正确使用。这确实不重要,并且与 websockets 与 http/2 的问题无关。 (3认同)
  • HTTP/2 确实支持双向连接,但这并不意味着 HTTP/2 废弃了 WebSockets。双向连接只能通过使用不打算在 Web-API 中公开的协议详细信息来建立。如果 HTTP/2 废弃了 WebSocket,那么 HTTP/1.1 也可能废弃 WebSocket。HTTP/1.1 已经支持使用 *Upgrade* 标头的双向连接。该标头后来用于通过 HTTP/1.1 实现 WebSocket。现在,我们似乎还获得了[使用 HTTP/2 双向功能的 WebSockets](https://tools.ietf.org/html/rfc8441)。 (2认同)
  • HTTP/2 未涵盖的 Web 套接字的具体用例是什么? (2认同)
  • @masonk 将二进制数据从 JS 应用程序双向流式传输到 HTTP 服务器。HTTP2 服务器推送到 JS 应用程序仅适用于服务器发送事件 (SSE),并且 SSE 无法处理二进制数据。 (2认同)
  • 在 websocket 中,服务器在客户端发起 websocket 升级请求之前无法开始推送任意字节,但随后它可以随时推送。在 HTTP/2 中,服务器在客户端发起数据连接之前无法开始推送字节,但随后它可以随时推送字节。功能上有什么区别?正如我所指出的,PUSH_PROMISE 功能是一种转移注意力的东西。这并不是 HTTP/2 取代 Web 套接字的原因。这只是一个小的性能优化。它与 HTTP/2 的核心(即 Bidi 流)无关。 (2认同)
  • @Myst:嗯,有一件事是肯定的:我们中的一个人误读了规范;) (2认同)
  • @Ezekiel:我想补充一点,HTTP/2 Push Promise 实际上会到达浏览器的想法有些误导。事实上,[Google 建议弃用该功能](https://groups.google.com/a/chromium.org/g/blink-dev/c/K3rYLvmQUBY/m/vOWBKZGoAQAJ?pli=1)。Push Promise 旨在将 CSS 和 Javascript 与原始页面一起推送。然而,实施经常被滥用或误用。Push Promise 从来就不是为推送通知而设计的,推送的资源可能永远不会被浏览器处理(因此永远不会影响本地缓存)。 (2认同)

Mys*_*yst 58

我说Nay(Websockets没有过时).

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

即(来自HTTP2草案):

中介可以从服务器接收推送,并选择不将它们转发到客户端.换句话说,如何利用推送的信息取决于该中介.同样,中间人可能会选择向客户端进行额外的推送,而不会对服务器采取任何操作.

此外,HTTP/2连接会在一段时间后关闭.

确实,该标准规定:

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

但...

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

即使相同的连接允许在打开内容时推送内容,即使HTTP/2解决了HTTP/1.1的'keep-alive'引入的一些性能问题...... HTTP/2连接也无法无限期保持打开状态.

一旦关闭,网页也不能重新启动HTTP/2连接(除非我们回到长拉,即).

编辑(2017年,两年后)

HTTP/2的实现表明,多个浏览器选项卡/窗口共享一个HTTP/2连接,这意味着push永远不会知道它属于哪个选项卡/窗口,从而无需使用它push作为Websockets的替代品.

  • 对于评论 HTTP/2 的推送的人来说,基本上是针对 HTML 页面的资源或其他此类相关资源,在请求之前推送它们。人们只是想到网页,还有其他情况,例如网络游戏。如果 WebSocket 已过时,那么这将不存在 https://tools.ietf.org/html/rfc8441 (5认同)
  • WS套接字也不会永远保持打开状态.差异是流; HTTP/2为您提供了多个流流,这意味着服务器上的流控制非常不同并且通常无锁.WS(作为协议)必须具有不受管制的入站处理.流量控制在堆栈上方实现.为了安全性和服务器完整性,HTTP/2比WS好得多. (3认同)
  • 浏览器可以轻松地关闭您的 WS 连接。这就是任何类型网络的生活。说实话,HTTP/2 中的多路复用有些大材小用了。该协议确实不需要它。打开多个流后,您会开始遇到 TCP 缓冲区限制吞吐量的问题。我同意你的观点,WS 比 HTTP/2 做得更好。从根本上来说,WS 需要很多更高级别的控制来防止用户做坏事。 (3认同)
  • 引用本叔叔(蜘蛛侠)的话:“记住,能力越大责任越大”。是的,@bond,你说得很对。Websockets 是一个非常“原始”的协议,需要更负责任的服务器设计。是的,WS 可以像 HTTP/2 一样轻松关闭,但 WS 支持 `onclose` 回调,因此不需要轮询。至于多路复用,我认为这是一种必要,而不是一种选择。`keep-alive` 失败了,避免“一线”性能下降的唯一方法是冒多路复用的风险。时间会告诉你:) (3认同)
  • @bond,我同意HTTP/2有很多优点**作为传输层**(在许多浏览器选项卡中共享一个连接只是一个例子).但是,它不是设计为**通信层**.这是一个功能性问题.两种协议都满足不同的需求 即使用Websockets在浏览器上实现`ssh`终端是一件轻而易举的事.这将是HTTP/2上的一个令人头痛的问题,特别是如果打开多个选项卡的话.此外,如果浏览器(或其中一个HTTP/2代理)关闭连接怎么办?客户可以假设没有新数据可用吗?我们回到民意调查. (2认同)
  • 从服务器设计的角度来看,出站复用是一个复杂且昂贵的问题。它需要 IO 机制进行内部轮询,这非常昂贵。除非您正在流式传输大型文档,否则多路复用甚至无法运行,因为在第二个文档变得可用之前,请求可能已在内部完全响应并缓冲,并且多路复用无法运行。RTMP 具有出站复用功能,但只有 Adob​​e 的服务器可以实现。令人惊讶的是,HTTP/2 与 RTMP 如此接近。 (2认同)

bon*_*ond 38

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

WS over HTTP/2将通过减少打开新连接的时间和允许更多通信信道而不增加更多套接字,软IRQ和缓冲器的费用来节省资源.

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


Jee*_*ash 18

好吧,引用这篇InfoQ文章:

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

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

  • HTTP2 Push 并不是为了让 websocket 变得过时。要将 utf-8 文本数据从服务器传输到客户端,您应该在 http2 中使用 SSE(服务器端事件)。其他方向可以使用传统的 POST 或 GET 请求,因为 http2 对于此类流量更加优化。它在所有给定流量中使用单个 TCP 连接。 (2认同)

小智 6

不,WebSocket 并没有过时。然而,HTTP/2 破坏了 HTTP/1.1 定义的 websocket(主要是通过禁止使用 Upgrade 标头进行协议更新)。这就是为什么这个 rfc:

https://datatracker.ietf.org/doc/html/rfc8441

定义了 HTTP/2 的 websocket 引导过程。


小智 5

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


Sho*_*use 5

截至今天,没有。

与 HTTP 相比,HTTP/2 允许您保持与服务器的连接。从那里,您可以同时拥有多个数据流。目的是即使没有客户端请求,您也可以同时推送多个内容。例如,当浏览器请求 a 时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.css并且index.js,因为浏览器会缓存,但没有这么多的数据包。

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


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


这里总结了每个目标:

  • HTTP - 使用一项资产响应请求
  • HTTP/2 - 响应具有多个资产的请求
  • SSE - 以单向文本 (UTF-8) 事件流响应
  • WebSocket - 创建双向二进制数据流