HTTP/2简述
1. HTTP 协议发展历史
- HTTP/0.9:1991年发布,及其简单,只支持GET请求
- HTTP/1.0:1996年5月发布,增加大量内容,引入二进制的HTTP消息体,支持在响应中发送图片和其他媒体文件。
- HTTP/1.1:1997年1月发布,进一步完善HTTP协议,引入管道化和分块编码,是当前最流行版本。
- SPDY:2009年谷歌发布SPDY协议,主要解决HTTP/1.1效率不高的问题
- HTTP/2:2015年基于SPDY协议实现发布,为了HTTP/2而不是HTTP/2.0,因为标准委员会不打算再发送子版本了,下一个版本将会是HTTP/3
1.1 SPDY协议
SPDY本质是向后兼容的,带来的风险和改动较少。SPDY引入一下概念:
- 流多路利用:请求和响应使用单个TCP连接传输数据,它们被分成不同的数据包,以流的方式分组。
- 请求优先级:同时发送所有请求时,为了避免引入新的性能问题,引入了请求优先级的概念。
- HTTP header压缩:body早就可以压缩了,现在header也可以压缩了。
2. HTTP/1.1提升性能方式
HTTP1.1 不是一种高效的协议,因为它为等待响应会阻塞发送,导致在当前请求完成之前,无法发送另一个请求。为了突破这种限制,有两种优化技术:
2.1 使用多个http请求
如大多数浏览器可以为每个域名打开6个连接,而为了进一步突破6个连接的限制,许多网站将域名进行拆分成多个子域名。但存在缺点:
- 启用多个http连接,客户端和服务端都有额外的开销:打开tcp连接需要的时间,维护连接需要更多的内存和CPU资源。
- 开启多个HTTP连接主要问题在于:没有充分利用底层TCP协议。
2.2 合并http请求
- 如前端图片,将需要的图片打包合并,通过一次请求访问到所需图片,这种打包技术叫作精灵图(雪碧图)。存在缺点:
- 这个方案会引入复杂度,创建精灵图需要额外的操作;
- 合并会导致文件的浪费,一些网页可能只需要用到精灵图中的一个图片,但是需要下载整个精灵图;
- 缓存问题,增加新的图片时,需要让浏览器再次下载整个精灵图。
HTTP2对Web性能的影响,HTTP2只是解决了网络性能,但是无法其他性能问题,如一张图片本省就很大。此外网络丢包情况下,会让HTTP/2变慢。
3. HTTP/2特性
3.1 二进制协议
HTTP/2是一个二进制的、基于数据包的协议,而HTTP/1是完全基于文本。基于文本协议方面人类阅读,但是机器解析起来比较困难。
使用基于文本的协议,要先发完请求,并接收完响应之后,才能开始下一个请求。即使HTTP/1.1引入管道化和分块编码,让消息分成多个块。但是会有队头阻塞(HOL)问题,即队列首部的消息会阻塞后面消息的发送。而且管道化在实际应用中没有得到很好的支持。
HTTP/2变成了一个完全的二进制协议,HTTP消息被分成清晰定义的数据帧发送,接收到所有数据帧后,可以将它们组合为完整的HTTP消息。所有HTTP/2消息都使用分块的编码技术,而且HTTP/2规范说明:HTTP/1.1定义的分块传输编码不得在HTTP/2中使用。
HTTP/2的二进制表示用于发送和接收消息数据,但是消息本身和之前的HTTP/1消息类似。二进制帧通常由下层可用户端(Web浏览器或Web服务器)或者类库来处理。所以在大多时刻,可以对HTTP/2连接和HTTP/1连接一视同仁。但理解HTTP/2帧,有助于问题排查。
3.2 多路复用
HTTP/1是一种同步的、独占的请求-响应协议。客户端发送HTTP/1消息,然后服务器返回HTTP/1响应。
HTTP/2允许在单个连接上同时执行多个请求,每个HTTP请求或响应使用不同的流。通过使用二进制分帧层,给每个帧分配一个流标识符,以支持同时发出多个独立请求。当接收到该流的所有帧时,接收方可以将帧组合成完整消息。帧是同时发送多个消息的关键,每个帧都标记着它属于哪个消息(流)。
HTTP/1访问方式
HTTP/2访问模式
HTTP/2使用单个TCP连接,对于每个请求都有一个新的、自增的流ID,返回响应时使用相同的流ID,响应完成后,流将被关闭且不能重用。而对应在HTTP/1上连接保持,可以重新用它来发送另外一个请求。
此外为了防止流ID冲突,客户端发起的请求使用奇数流ID,服务端发起的请求使用偶数流ID(服务端推送,但也要客户端先发起请求后推送)。流ID为0是客户端和服务器用户管理连接的控制流。
3.3. 流量控制
接收方处理消息慢于发送方,就会存在挤压,需要把数据放入缓冲区,当缓冲区满时会导致丢包,需要重新发送。在TCP层支持限流。但是HTTP/2要在流的层面上实现流量控制。如视频网站,如果用户暂停视频,可以仅暂停视频流,但允许加载网站的其他资源。
但目前的实现基本无法控制,只是协议层面的支持而已。
3.4 数据流优先级
当数据帧在排队时,服务器会给高优先级的请求发送更多的帧。而HTTP/1中,不同连接是相互独立的,没有优先级关系,无法指定连接的优先级。
但目前的实现基本无法控制,只是协议层面的支持而已。
3.5 首部压缩
HTTP header(包括请求和响应),有很多是重复的,如:Cookie、User-Agent、Host、Accept、Accept-Encoding等。HTTP/1允许压缩HTTP body内容,但是不会压缩HTTP header。HTTP/2引入首部压缩的概念,使用了和正文不同的压缩技术。
HTTP/2 header压缩叫作HPACK,基于查询表和Huffman编码,而不是基于反查的压缩方法,该方法会出现CRIME(Compression Ratio Info-leak Made Easy)攻击。
HPACK有一个静态表,包含61个常见的HTTP首部名称。此处不一一列举,此外内置,为规范中定义的。
HPACK还有一个连接级的动态表,从位置62开始,最大到SETTING帧的SETTINGS_HEADER_TABLE_SIZE所定义大小,默认为4096。当达到最大值时,最老的记录会被删除。为了简化这个过程,在写入表时,每个条目的id都会递增。例子如下两个自定义首部:
Header 1 : Value 1
Header 2 : Value 2
开始给Header 1分配位置为62,当发送header 2时,Header 2被移到63,然后将header 2记录为62.
一个首部在表中的位置不是静态的,当前请求和后续请求中信的首部被添加到表中时,它随之增长。处于这个原因,必须顺序接收HEADERS和CONTINUATION帧以维护这个动态表的完整。TCP确保其有序,所以在HTTP/2中,每个TCP连接有一个唯一的动态表。
HPACK动态表是可以设置的,总共有4种类型,不同类型的请求格式不同,具体不阐述,如有需要再仔细阅读相关文档。
在HTTP/2协议规范上,并没有要求发送方一定要使用动态表,如Nginx服务器只使用静态表。
3.6 服务端推送
HTTP/2添加了服务端推送的概念,它允许服务端给一个请求返回多个响应。但服务端推送如果使用不当,很容易浪费带宽。决定在什么时候推送、如何推送,是利用服务端推送的关键。
4.HTTP/2 升级
4.1 浏览器支持情况
- 绝大多数浏览器都支持HTTP/2,但是要求在https协议下。而且有些浏览器会要求只有服务器支持ALPN(Applicatoin Layer Protocol Negotiation,应用层协议协商)才会支持HTTP/2。
- 许多浏览器在使用HTTP/2之前需要更新为更安全的加密套件。
- 有些浏览器与底层操作系统绑定,特别是移动设备上,如Safari,那么就需要升级操作系统才能让浏览器版本升级以支持HTTP/2。
4.2 服务器支持情况
流行的Web服务器支持HTTP/2的版本情况如下,如果要让服务器支持,就需要升级到对应的版本。
此外就是严格的HTTPS要求:大多数Web服务使用单独的库(通常是OpenSSL)来处理SSL/TLS。此加密库通常是操作系统的一部分,尽量升级Web服务器已经很麻烦了,但是升级SSL/TLS通常更加困难,因为可能会影响服务器上其他所有软件。如ALPN仅在最新版本的OpenSSL(1.0.2及更高的版本)支持,很多标准版本并不支持。RedHat和CentOS仅在2017年8月和9月分别增加了对OpenSSL 1.0.2的支持,但是Apache等网络服务器打包版本通常基于旧的1.0.1版本编译。
| Web服务器 | HTTP/2支持的版本 |
|---|---|
| Apache HTTPD | 2.4.17 |
| IIS | 10.0 |
| Jetty | 9.3 |
| Netty | 4.1 |
| Nginx | 1.9.5 |
| Node.JS | 8.4.0 |
| Tomcat | 8.5 |
4.3 反向代理
反向代理很场景,主要用于以下场景:
- 负载均衡
- 卸载一些功能:如HTTPS或者HTTP/2
通常在Web服务器前,会增加反向代理服务器(如Nginx),此时它可以将用户的HTTP/2请求转换为HTTP/1.1请求,发送到Web服务器上。
如果反向代理服务器不支持HTTP/2,那么即使Web服务器支持HTTP/2,连接也会降级为HTTP/1.1连接。
基于反向代理实现HTTP/2时,HTTP/2连接在反向代理处终止,使用另外的连接(如HTTP/1.1)到真实的服务上。反向代理到真实服务器上并不太需要使用HTTP/2
-
HTTP/2主要优点是可以提升高延迟、低带宽连接的速度,连接到边缘服务器(反向代理)的用户通常处于这样的网络环境下。从反向代理到实际服务器的流量一般处于低延迟、高带宽、短距离的网络环境中,通常不需要koalaHTTP/1.1的性能问题。
-
即使采用HTTP/2,采用HTTP/2单个连接的方式收益也不高。甚至担心使用单个连接可能会导致性能问题。如Nginx已经声明,不会为代理为代理连接实现HTTP/2.
Q: Will you support HTTP/2 on the upstream side as well, or only support HTTP/2 on the client side?
A: At the moment, we only support HTTP/2 on the client side. You can’t configure HTTP/2 with
proxy_pass. [Editor – In the original version of this post, this sentence was incorrectly transcribed as “You can configure HTTP/2 withproxy_pass.” We apologize for any confusion this may have caused.]But what is the point of HTTP/2 on the backend side? Because as you can see from the benchmarks, there’s not much benefit in HTTP/2 for low‑latency networks such as upstream connections.
Also, in NGINX you have the keepalive module, and you can configure a keepalive cache. The main performance benefit of HTTP/2 is to eliminate additional handshakes, but if you do that already with a keepalive cache, you don’t need HTTP/2 on the upstream side.
4.4 CDN
CDN和反向代理类似,可以在CDN服务器上启动HTTP/2,而源站只需要支持HTTP/1.1就行了。
5. HTTP/2对比HTTP/1.1
http首部压缩,节省了大量请求数据。特别是请求端,请求时首部数据比较大,Cloudflare是最大的CND厂商之一,其声称,启用HPACK时,请求数据减少了53%,响应节省了1.4%(响应的body比header大的多)
HTTP/2优势:
- 首部压缩解决带宽问题
- 多路复用(基于流)解决tcp连接数量问题。
6. 参考资料
- 《Http2实战》