原文地址:Will WebSocket survive HTTP/2? (如有错误,欢迎大家批评指正,谢谢)。
互联网所依赖的协议正——HTTP,正处于一个重大的转变之中。这个转变带来了大量的疑问和关切,关于HTTP/2,正面负面的评价都有。尽管HTTP/2带来了很多新的能力,但是它并不能完全取代现有的推送技术和流技术。
关于HTTP/2,第一个需要注意的点是,它并非HTTP的完全替代品。请求方法、状态码和多数的头和现在保持一致。HTTP/2旨在提高数据在网络上的传输效率。
先看一下它同HTTP/1.x的关键不同之处,以及其解决的相关问题:
现在,如果我们将HTTP/2同Websocket对比一下,我们能看到一些类似的地方:
HTTP/2 |
Websocket |
|
头 |
压缩(HPACK) |
无 |
二进制 |
是 |
二进制或者文本 |
多路复用 |
是 |
是 |
优先级 |
是 |
否 |
压缩 |
是 |
是 |
方向 |
客户端/服务器+服务器推送 |
双向 |
全双工 |
是 |
是 |
有了这些改进和类似的能力,很自然地就会问:HTTP/2是Websocket或者SSE这类推送技术的替代品吗?
答案显然是否定的,理由很简单:正如我们上面所看到的,HTTP/2引入了服务器推送,让服务器能够主动地推送资源到客户端缓存。然而它并没有允许推送数据到客户端应用本身。服务器的推送只是由浏览器来处理,并不会让应用代码介入,这也就意味着应用程序无法使用API来获取这些事件的通知。
这里就来到了“服务器发送事件”(Server-Sent Events SSE)的舞台了。SSE是一种让服务器能够在客户端服务器建立连接之后异步推送数据给客户端的机制。这样服务器就可以在数据“块”准备好之后再发送数据。这可以被看成是一种单向的发布订阅模型。多数的现代浏览器也实现了W3C HTML5标准中一个叫做EventSource的标准JavaScript客户端API。那些不支持EventSource API的浏览器,也可以方便地通过填充的方式来获得相应的支持。
由于SSE是基于HTTP的,其天然适配于HTTP/2,这样SSE就可以集两者之长:HTTP/2可以基于多路复用流形成一个高效传输层,同时SSE给应用提供了API使之能够进行推送。
为了完全理解流和多路复用是什么,我们先来看一下IETF的定义:“流”就是一个独立的、在客户端服务器之间的HTTP/2连接上双向的帧序列。其重要的一个特征就是单个的HTTP/2连接可以包含多个并发开启的流,其中每个端点都交错着来自多个流的帧。
为了避免上述的定义将你整得云里雾里(我就是如此:-)),下面的这一张来自于Nginx博客的图片清晰地解释了其意义:
如果想要实验一下HTTP/2多路复用是如何在实际中工作的,可以尝试一下这个demo,不要忘了使用你喜欢的浏览器打开开发者窗口。如果你不确定你的浏览器是否支持HTTP/2,可以快速浏览一下这里。
使用HTTP/1,应该会有如下的输出:
浏览器会并行打开多个HTTP/1.x连接来加速页面加载。不同的浏览器对于针对统一域名并发打开的连接数量有不同的限制,基本上都会支持6个左右不同的连接。为了克服这个限制,类似于域名分片的技术就被用来将资源分布在多个域名上。这些技术(我们可以将其认为是非法入侵)包括连接JavaScript和CSS文件、图像和资源内联,在HTTP/2世界中反而适得其反。这可能是迁移到HTTP/2的时候收到的最主要的影响了:消除多年以来所做的优化。
当使用HTTP/2的时候,会看到浏览器使用单个多路复用的连接,带来更快的加载时间。
现在我们已经了解了什么是多路复用,我们必须始终记得SSE是基于HTTP的。这意味着使用HTTP/2的时候,不仅仅可以在一个TCP连接上交错多个SSE流,同时也支持多个SSE流(服务器到客户端)服务多个客户端请求(客户端到服务器)。有了HTTP/2和SSE,我们现在就可以使用一个纯HTTP双向连接,加之使用简单的API使应用代码注册多个服务器推送。双向能力的缺失一直是SSE对比Websocket时最主要的短板。有了HTTP/2就弥补了这个短板。这就为跳过Websocket并坚持使用基于HTTP的机制提供了可能。
回答开始提出的问题:有了HTTP/2,Websocket还有市场吗?
答案是肯定的,主要是因为它已经被大量应用,同时在某些特定应用场景下,其底层设计致力于双向能力,拥有较少的负载的优势就会体现出来。假设需要在双端之间交互大吞吐量的消息,其中上下流动的消息量大致差不多(比如,需要保持所有玩家同步的大型多人在线游戏),这种场景下Websocket可能会是更好的选择。
如果考虑像是展示实时市场新闻、市场数据、聊天应用等场景的时候,依赖HTTP/2+SSE会提供高效的双向通信通道并保有留在HTTP世界的大量优势:
总结一下
Websocket技术可能会继续使用,但是SSE和其EventSource API同HTTP/2的能力相结合可以在多数场景下达到同样的效果,但是会更简单。