5. http2的基本概念
http2到底做了些什么呢?而HTTPbis小组究竟又应该把它制定到什么样的程度呢?
事实上,http2有着非常严格的边界,这也给小组成员的创新带来了些许限制。
http2必须维持HTTP的范式。毕竟它只是一个让客户端发送请求到服务器的基于TCP的协议。
不能改变 http:// 和 https:// 这样的URL,也不能对其添加新的结构。使用这类URL的网站太多了,没法指望他们全部改变。
HTTP1的服务器和客户端依然会存在很久,所以我们必须提供HTTP1到http2服务器的代理。
随后,我们也要让这种代理能够将http2的功能一对一的映射到HTTP 1.1的客户端。
删除或者减少协议里面那些可选的部分。虽然这并不算的上是一个需求,但是SPDY和Google的团队都非常喜欢这点。通过让协议里所有的内容都成为了强制性要求,可以防止人们在实现的时候偷懒,从而规避一些将来可能会发生的问题。
不再使用小版本号。服务器和客户端都必须确定自己是否完整兼容http2或者彻底不兼容。如果将来该协议需要被扩充或者变更,那么新的协议将会是http3,而不是http 2.x。
5.1. http2和现有的URI结构
如上所述,现有的URI结构正在被HTTP 1.x使用而不能被更换,所以http2也必须沿用该结构。因此不得不找到一种方式将使用的协议升级至http2,比如可以要求服务器让它作响应时使用http2来替代旧的协议。
HTTP 1.1本身就制定过“升级”的方案:提供一个首部字段,表示允许服务器在收到旧协议请求的同时,可以向客户端发送新协议的响应。但这一方案往往需要花费一次额外的往返通信来作为升级的代价。
而这一代价是SPDY团队不想接受的。因为他们只实现了基于TLS的SPDY,所以他们开发了一个TLS的扩展去简化协议的协商。这个扩展被称作NPN(Next Protocol Negotiation),借助于此,服务器会通知客户端所有它支持的协议,让客户端从中选择一个合适的来进行通讯。
5.2. 为 https:// 所准备的http2
有相当多的人关注到了http2可以在TLS上正常的运作,而SPDY依赖于TLS,所以按理说TLS也应成为http2 必需的组件,不过出乎大家意料的是http2将TLS标记成了可选。然而,全球两大浏览器领导者 —— Firefox和Chrome都明确地表示,他们只会实现基于TLS的http2.
选择TLS的原因的其中之一是希望保护以及尊重用户的隐私,而早期的评估结果也表明,在TLS上建立新的协议更有可能获得成功。而这其中部分原因是人们普遍认为任何来自80端口的流量都是基于HTTP 1.1亦或者是其某个变种的,而不是另外一种全新的协议。
关于是否应该强制使用TLS的主题在邮件组内和会议上引起了不小的争议 —— 这到底是好是坏呢?不管怎么样,对于这种备受争议的话题还是请谨慎讨论,尤其是当你面对一个HTTPbis小组成员的时候。
诸如此类,还有一个激烈而长期的讨论,即:如果选择了使用TLS,那http2是否应该强制规定密码列表,也许应该建立起一个黑名单,又或者它根本就不需要从TLS层得到任何东西。不过这个问题还是留给TLS工作组去解决吧,最后的规范中指定了TLS最低版本为1.2,并且会有加密组的限制。
5.3 基于TLS之上的http2协商
Next Protocol Negotiation (NPN)是一个用来在TLS服务器上协商SPDY的协议。IETF将这个非正式标准进行规范化,从而演变成了ALPN(Application Layer Protocol Negotiation)。ALPN会随着http2的应用被推广,而SPDY的客户端与服务器则会继续使用NPN。
由于NPN先于ALPN诞生,而ALPN又经历了一些标准化过程,所以许多早期的http2客户端和服务器在协商http2时会将这两者同时实现。与此同时,考虑到SPDY会使用NPN,而许多服务器又会同时提供SPDY以及http2,所以在这些服务器上同时支持ALPN以及NPN显然会成为最理所当然的选择。
ALPN和NPN的主要区别在于:谁来决定通信协议。在ALPN的描述中,是让客户端先发送一个协议优先级列表给服务器,由服务器最终选择一个合适的。而NPN则正好相反,客户端有着最终的决定权。
5.4 为 http:// 所准备的http2
正如我们之前所提到的,对于纯文本的HTTP1.1来说,协商http2的方法就是通过给服务器发送一个带升级头部的报文。如果服务器支持http2,它将以“101 Switching”作为回复的状态码,并从此开始在该连接上使用http2。也许你很容易就发现这样一个升级的流程会需要消耗掉一整个的往返时延,但好处是http2连接相比HTTP1可以被更大限度地重用和保持。
虽然有些浏览器厂商的发言人宣称他们不会实现这样的http2会话方式,但IE团队已公开表示他们会实现,与此同时,curl也已经支持了这种方式。