HTTP/2协商机制

HTTP/2部署使用一文介绍了如何部署HTTP/2到我们的应用或Web站点中。这时,正如部署HTTPS一样,大家会疑问:

  • 发起HTTP/2的请求与HTTP1.x的请求有区别么?
  • 客户端与服务端如何确定HTTP1.x与HTTP/2的请求?
  • 部署HTTP/2一定要升级到HTTPS么?

带着这些疑问,我们一起来分析HTTP/2的协商机制。

发起HTTP/2请求

HTTP/2的设计之初是不改动HTTP的语义,HTTP方法、状态码、URI及首部字段等核心概念,即不期望像用户暴露出HTTP2实现的复杂性。HTTP/2依然与HTTP/1.x保持一致,使用httphttps来完成请求,前者对应于h2c(Http2 over cleartext TCP),后者则对应于h2(Http2 over TLS)

所以,在发起Http请求时,对于HTTP/2和HTTP1.0其实没有任何区别。对于同样的URI:https:\\www.baidu.com或者http:\\www.baidu.com,客户端在发起新请求之前,必须能发现服务器及所有设备是否支持HTTP/2协议,这就依赖于双端对于协议的协商机制了。

HTTP/2协商

HTTP/2协议包含两种实现类型:h2C,基于常规的非加密信道建立的HTTP/2的连接;h2,基于TLS协议建立起来的HTTP/2的连接。针对h2Ch2,协商的方式是不同的。

h2c的升级协商

HTTP1.1中引入了Upgrade机制,使得客户端和服务端之间可以借助已有的HTTP语法升级到其他协议。对于h2c的升级,正是借助Upgrade来完成的。

客户端必须通过Upgrade头部列出要升级到的协议和版本,并且还要包含一个HTTP2-Settings的头部,如下:

GET / HTTP/1.1
Host: server.example.com
Connection: Upgrade, HTTP2-Settings
Upgrade: h2c
HTTP2-Settings: <base64url encoding of HTTP/2 SETTINGS payload>

如果服务器不支持HTTP/2,便会忽略upgrade头部,直接回应Http1.x的Response。

HTTP/1.1 200 OK
Content-Length: 243
Content-Type: text/html

...

如果服务器支持HTTP/2,则会以101的状态码回应,并且可以在响应正文,直接发送HTTP/2的帧。

HTTP/1.1 101 Switching Protocols
Connection: Upgrade
Upgrade: h2c

[ HTTP/2 connection ...]

下图是通过nghttp2分析HTTP1.x升级到HTTP/2的细节:

h2的升级协商

基于TLS的HTTP/2协商则依赖于ALPN协商机制。起初,Google在SPDY协议中开发了一个名为NPN(Next Protocol Negotiation,下一代协商)的TLS扩展,随着SPDY被HTTP/2所取代,NPN也被修订为ALPN(Application Layer Protocol Negotiation,应用层协议协商)

在TLS握手阶段,通信双方原本就要进行加密套件等的协商,ALPN作为起拓展加入握手协商过程中,对通信不会增添性能影响。

下图通过Wireshark对HTTP/2的连接建立过程进行分析:

从上面wireShark的抓包分析来看,客户端在建立TLS连接的Client Hello握手中,通过ALPN扩展列出了自己支持的各种应用层协议。

如果服务端支持h2的话,会在server Hello中指定ALPN的结果为h2.随着TLS连接建立成功,便可以进行HTTP2.0的系列请求了。

如果不支持,会从客户端的ALPN列表中选一个自己支持的(HTTP/1.1)。随后的请求都基于HTTP/1.1来完成。

小结

在了解HTTP/2的协商机制后,应该不会在困惑于开篇的几个问题了。HTTP/2 协议本身并没有要求它必须基于 HTTPS(TLS)部署,但是考虑到HTTPS协议的安全性,而且当前主流浏览器都只支持基于HTTPS的HTTP/2。所以考虑安全性和兼容性,我们通常需要基于HTTPS部署。


网易云新用户大礼包:https://www.163yun.com/gift

本文来自网易实践者社区,经作者何慧授权发布。