HTTP/2 是 HTTP 协议的第二个正式版本,于 2015 年 5 月 15 日正式发布,到现在短短半年时间里已经获得了大量的关注和实现支持。本文将介绍其核心的理念和相关知识要点。
可以通过访问 Akamai HTTP/2 测试页 来体会性能提升效果。本地测试结果差一个数量级 。
为何要有 HTTP/2
主要目标是优化性能,次要目标是安全性和互操作性。其实也是因为现在越来越多的 Web 应用,对性能等方面的需求。
最早的 HTTP/1.0 (RFC 1945,1996 年发布)中每个资源(文本、图片)默认要单独创建一个 TCP 连接来传输。创建一个 TCP 连接的时间成本是比较高的。
HTTP/1.1 (RFC 2616,1999 年发布,最近替代的是 2014 年 RFC 7230)是目前互联网世界的主流协议,通过优化对 TCP 连接的使用来提高效率,主要改进包括:
- 默认采用持久化连接:同一个网页上的所有资源可以共用一个 TCP 连接;
- 请求的流水化:多个请求可以不用等前面请求完成就一次性顺序发出(但应答消息还得顺序返回);
- 其它特殊头字段(Host、Keep-Alive、Range 等)支持更多语义。
注:RFC 7230 中去掉了一个域名最多 2 个连接的限制。
来源
项目主页在 http2.github.io。
HTTP/2 规范内容是基于 Google 提出的 SPDY 的 3 号草案,这也是为何实现如此之快。
Google 后来基于 SPDY 提了一个 QUIC 协议,试图基于 UDP 来实现类似 HTTP/2 的效果。
注:UDP 和 TCP 之争由来已久,只能说两者各有适合的场景,不能简单对比。
具体内容
核心思路是在继续遵循 HTTP 规范的前提下,(通过多路复用等手段)进一步提高对 TCP 连接的利用率,减少无谓的等待时间;同时采用头部压缩减少传输量。
实现上,在应用层(HTTP/2)和传输层(TCP or UDP)之间增加一个二进制分帧层(分为 Header 帧和 Data 帧)。加层的做法果然是 IT 行业的瑞士军刀。
跟 HTTP/1.1 比,没变的:
- HTTP 方法
- HTTP 状态码
- HTTP 语义
意味着原先基于 HTTP 设计的 API 照样可用。
改进的地方主要包括:
- 用二进制流(Stream)代替原先的文本格式,一个连接可以并发多个流;
- 流支持优先级和对其他流的依赖;
- 流通过单独的窗口来控制流量;
- 流可以通过重置帧来中断前面发出的消息;
- 头部信息支持压缩(HPACK);
- 除了客户端请求,服务器端也可以主动推送资源(例如页面中的各种元素资源);
- TLS 规范中是可选的,但实现上 Chrome 和 Firefox 仅支持 TLS。
其中,HPACK 是采取基于字典(包括预置的静态字典和动态添加的动态字典)的压缩机制 + Haffman 编码进行编码。原来的域值现在只需要使用对应索引号即可。
相关规范
相关的两个 RFC:
前者是 HTTP/2 主体内容的规范,后者是头部压缩技术(HPACK)的规范。
正式版本之前先后经过 0~17 等 18 次草稿。
一般,通过 h2-x 表示是协议的第几版本草稿,h2 默认表示正式版。
技术组
包括 IETF HTTP Working Group 和 IETF Httpbis。
前者是关于 HTTP 协议的官方机构;后者 2007 年成立,负责更新 HTTP/1.1 规范,是 RFC 7230 的提出者。
支持 HTTP/2 的项目
除了知名浏览器,其它项目包括 Apache HTTP Server 2.4.17+,Nginx,Chromium,curl,Jetty,Netty,Nodejs ,Wireshark等。
此外,部分国外网站也已经默认开启 HTTP/2 支持。
这里有 完整列表。