HTTP/2(Hypertext Transfer Protocol Version 2)无疑是下一代互联网加速技术的基石与方向,自诞生以来经历了00~17 共 18 版草案,目前,已经拥有了明确的RFC标准:RFC 7540和RFC 7541。
目前支持 HTTP/2 的浏览器有 Chrome 41+、Firefox 36+、Safari 9+、Windows 10 上的 IE 11 和 Edge。服务器方面则有 F5、H2O、nghttp2 等数十种选择,各种语言实现的都有。Nginx自1.9.5版本开始支持HTTP/2的http_v2_module模块,在这个过程中修复了一些bug,目前稳定的版本是nginx-1.10.1。另外,移动端开发可以使用OkHttp来实现HTTP/2。
综上所述,无论是移动APP还是浏览器,无论是客户端还是服务端,都已经具备了支持HTTP/2的能力,HTTP/2已经是大势所趋,笔者将基于nginx-1.10.1来实现HTTP/2,并分析HTTP/2的性能优势,结合其特点来确定如何在线上环境中得到有效应用。
1.HTTP/2原理
如果要深入讲解HTTP/2的原理,一节的内容是远远不够的,后期笔者会专门来做一个HTTP/2的系列。那本节内容主要对HTTP/2的改动与优势做简单介绍,并且回答两个问题(这两个问题也曾深深困扰着我):1. 如果浏览器不支持HTTP/2,而服务端开启了HTTP/2,会否有兼容性影响?2. HTTP/2请求是否一定要是HTTPS请求呢?通过这些对HTTP/2有一个全面的认识。
1.1 HTTP/1的弊端
先来说说HTTP/1.1的问题,这里请原谅笔者的啰嗦,需要把事情说清楚。
基本的HTTP/1.1是基于文本格式的,单个请求单个连接,客户进程建立一条同服务器进程的TCP连接,然后发出请求并读取服务器进程的响应。服务器进程关闭连接表示本次响应结束。因此,页面加载开销是非常大的。
为此,HTTP/1.1自然不会坐以待毙,也做了一些优化,包括:
- 浏览器并发控制Pipelining:
浏览器Pipelining是将同一Host的多个HTTP请求整批提交的技术,而在传送过程中不需先等待服务端的回应。不同浏览器的并发数是不同的,比如IE是默认两个请求。
为了使Pipelining的效益最大化,需要将请求的域名Host分散,如下图所示:
而这样,其弊端是很明显的,不同Host需要额外的寻址消耗,会导致DNS时间增长,尤其当某些地区DNS解析不稳定时,甚至会导致大量请求的阻塞,得不偿失。
- HTTP Keep-Alive:
即我们常见的:Connection:keep-alive
。数据传输完成了保持TCP连接不断开,等待在同域名下继续用这个通道传输数据。这样就减少了TCP的建连次数。
需要注意的TCP Keep-Alive和HTTP Keep-Alive是不同层次上的概念,TCP的keep alive是检查当前TCP连接是否活着;HTTP的Keep-alive是要让一个TCP连接在timeout周期内永久存活。
一般而言,HTTP Keep-Alive和Pipelining技术是相结合使用的,这样同一个域名下的请求就能实现并发而非串行,然而,事情真的有我们想的那么好嘛?
线头阻塞问题:由于要求服务端返回响应数据的顺序必须跟客户端请求时的顺序一致,这容易导致Head-of-line blocking:第一个请求的响应发送影响到了后边的请求,因为这个原因导致HTTP流水线技术对性能的提升并不明显。
另外,由于域名是分散的,同一个站点,浏览器往往要保持8-10条长连接,资源消耗更大了。
综上所述,由于HTTP/1.1协议本身的缺陷(基于文本,过于简单),即使是已有的优化,也无法满足日益增长的性能需求。
1.2 HTTP/2的优点
HTTP/2的优点总结为一个字,就是“快”:
HTTP/2是完全多路复用的,而非有序并阻塞的;
请求优先级
使用报头压缩,HTTP/2降低了开销
HTTP/2实现了服务端响应的主动推送
1.2.1 多路复用
完全的多路复用是HTTP/2的核心,HTTP/2采用二进制帧格式而非文本格式进行传输,单个连接内多个流(请求-响应)之间并行处理,减少网路资源占用,可避免了TCP频繁的打开、关闭。如下图所示,一言以蔽之,对一个站点,现在只需建连一次,就可以多路复用。
通过Wireshark抓包,可以明显对比看到HTTP/1.1和HTTP/2的区别:
HTTP/1.1的包是典型的一条请求发出,等待响应,响应后再发第二条请求,再等待响应。