我正在学习HTTP / 2协议。这是带有小消息帧的二进制协议。它允许通过单个TCP连接进行流多路复用。从概念上讲,它似乎与WebSockets非常相似。
是否有计划淘汰Websocket,并用某种无头HTTP / 2请求和服务器启动的推送消息替换它们?还是WebSockets可以补充HTTP / 2?
我正在学习HTTP / 2协议。这是带有小消息帧的二进制协议。它允许通过单个TCP连接进行流多路复用。从概念上讲,它似乎与WebSockets非常相似。
是否有计划淘汰Websocket,并用某种无头HTTP / 2请求和服务器启动的推送消息替换它们?还是WebSockets可以补充HTTP / 2?
Answers:
据我了解,HTTP / 2不是websocket的替代品,而是旨在标准化SPDY协议。
在HTTP / 2中,幕后使用server-push来改善客户端从浏览器的资源加载。作为开发人员,您在开发过程中并不十分在意。但是,使用Websocket,允许开发人员使用API,该API能够使用唯一的全双工连接来使用和推送消息。
这些不是同一回事,它们应该相互补充。
在刚刚阅读完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 的真实示例。
我说不(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
它将永远不知道它属于哪个选项卡/窗口,从而消除了使用push
Websockets的替代方法。
编辑(2020)
我不确定为什么人们会开始拒绝答案。如果有的话,自最初发布答案以来的几年证明,HTTP / 2不能替代WebSockets,并且并非旨在这样做。
诚然,HTTP / 2可以被用来隧道 WebSocket连接,但这些隧道连接仍然需要WebSocket协议的时候,就会实现HTTP / 2容器的行为方式。
ssh
使用Websockets时,在浏览器上实现终端是一件轻而易举的事情。HTTP / 2会让您头疼不已,特别是如果打开了一个以上的选项卡。另外,如果浏览器(或HTTP / 2代理之一)关闭连接怎么办?客户可以假设没有新数据可用吗?我们回到了投票。
onclose
回调,因此不需要轮询。至于多路复用,我认为这是必要的,而不是选择。keep-alive
失败,避免“第一线”性能下降的唯一方法是冒险复用。时间会证明
答案是不。两者之间的目标有很大的不同。甚至还有一个用于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
好吧,引用此InfoQ文章:
好吧,答案很显然是不行的,原因很简单:正如我们上面所看到的,HTTP / 2引入了服务器推送,它使服务器能够主动将资源发送到客户端缓存。但是,它不允许将数据下推到客户端应用程序本身。服务器推送仅由浏览器处理,不会弹出应用程序代码,这意味着应用程序没有API可以获取这些事件的通知。
因此,HTTP2推送确实是您的浏览器和服务器之间的东西,而Websockets确实公开了可供客户端(javascript(如果其在浏览器上运行))和应用程序代码(在服务器上运行)可用于传输实时数据的API。
可以通过Http / 2复用和WebSockets进行消息交换和简单的流传输(不是音频,视频流传输)。因此存在一些重叠,但是WebSocket具有完善的协议,大量的框架/ API和较少的标头开销。 这是有关该主题的不错的文章。
截至今天为止。
与HTTP相比,HTTP / 2允许您维护与服务器的连接。从那里,您可以同时拥有多个数据流。目的是即使您没有客户端请求,也可以同时推送多个内容。例如,当浏览器要求输入时index.html
,服务器可能还希望推送index.css
和index.js
。浏览器并没有要求它,但是服务器可能会在不询问的情况下提供它,因为它可以假设您将在几秒钟内想要得到它。
这是比获得的HTTP / 1方案快index.html
,解析它,发现它需要index.js
并index.css
和再建设2个这些文件的其他请求。HTTP / 2使服务器可以推送客户端甚至不需要的数据。
在这种情况下,它与WebSocket相似,但实际上并不是设计使然。WebSocket应该允许类似于TCP连接或串行连接的双向通信。这是一个彼此通信的套接字。而且,主要区别在于您可以发送任何原始数据字节中的任意数据包,而不用HTTP协议封装。标头,路径,查询字符串的概念仅在握手期间发生,但WebSocket会打开数据流。
另一个区别是,您可以使用Javascript对WebSocket进行更精细的访问,而使用HTTP,则由浏览器处理。使用HTTP所能获得的就是XHR
/中可以容纳的所有内容fetch()
。这也意味着浏览器将得到截获并修改HTTP头,不你能够控制它(如:Origin
,Cookies
等)。同样,HTTP / 2能够推送的内容也会发送到浏览器。这意味着JS并不总是(如果有的话)知道事物被推送。同样,这是有道理的index.css
,index.js
因为浏览器将对其进行缓存,但对于数据包则没有那么多。
确实是所有名称。HTTP代表超文本传输协议。我们致力于转移资产的概念。WebSocket是关于建立套接字连接的,双向二进制数据在该套接字连接中传递。
我们没有真正讨论的是SSE(服务器发送事件)。将数据推送到应用程序(JS)并不是HTTP / 2的意图,而是用于SSE的。使用HTTP / 2确实增强了SSE。但是,当重要的是数据本身而不是到达变量端点时,这并不是WebSockets的真正替代。对于使用WebSocket的每个终结点,都会创建一个新的数据流,但是使用SSE,它会在已存在的HTTP / 2会话之间共享。
这里总结了每个目标: