关于HTTP 2.0应该知道的事

HTTP 2.0的优势

相比HTTP/1.xHTTP/2在底层传输做了很大的改动和优化:
1.每个服务器只用一个连接:HTTP/2对每个服务器只使用一个连接,而不是每个文件一个连接。这样,就省掉了多次建立连接的时间,这个时间对TLS尤其明显,因为TLS连接费时间;
2.加速TLS交付:HTTP/2只需一次耗时的TLS握手,并且通过一个连接上的多路利用实现最佳性能。HTTP/2还会压缩首部数据,省掉HTTP/1.x时代所需的一些优化工作,比如拼接文件,从而提高缓存利用率;
3.简化Web应用:使用HTTP/2可以让Web开发者省很多事,因为不用再做那些针对HTTP/1.x的优化工作了;
4.适合内容混杂的页面:HTTP/2特别适合混合了HTML、CSS、JavaScript、图片和有限多媒体的传统页面。浏览器可以优先安排那些重要的文件请求,让页面的关键部分先出现、快出现,而且根本不会发生“浏览器明明在等关键的CSS和JS,而服务器还在发送黄图”的尴尬局面;
5.更安全:通过减少TLS的性能损失,可以让更多应用使用TLS,从而让用户信息更安全。

HTTP 2.0性能增强之二进制分帧

HTTP的定义大家都知道,叫超文本协议,也就是说http1.x的解析是基于文本。基于文本协议的格式解析存在天然缺陷,文本的表现形式有多样性,要做到健壮性考虑的场景必然很多。但是在HTTP/2里这里做了比较重大的改动—二进制分帧HTTP/2在应用层(HTTP)和传输层(TCP or UDP)之间增加一个二进制分帧层。在这个新增的二进制分帧层里HTTP/2会将所有传输的信息分割为更小的消息和帧,并对它们采用二进制格式的编码 ,其中HTTP1.x的首部信息会被封装到Headers帧,而我们的request body则封装到Data帧里面。二进制与之前的文本不同,二进制只认0和1的组合。基于这种考虑http2.0的协议解析决定采用二进制格式,实现方便且健壮。
paradin

HTTP/2的格式定义十分高效且精简。length定义了整个frame的大小,type定义frame的类型(一共10种),flagsbit位定义一些重要的参数,stream id用作流控制,payload就是request的正文,如下图:
paradin

HTTP 2.0性能增强之首部压缩

虽然HTTP/2引入了二进制分帧的概念,但是试想如果所有的二进制帧都会带上Headers帧,这是多大的数据冗余传送啊。于是HTTP/2针对这个需求又搞出来一个东东—“首部表”。

“首部表”来跟踪和存储之前发送的键-值对,对于相同的数据,不再通过每次请求和响应发送;通信期间几乎不会改变的通用键-值对(用户代理、可接受的媒体类型等等)只需发送一次。事实上,如果请求中不包含首部(例如对同一资源的轮询请求),那么首部开销就是零字节。此时所有首部都自动使用之前请求发送的首部。如果首部发生变化了,那么只需要发送变化了数据在Headers帧里面,新增或修改的首部帧会被追加到“首部表”。首部表在HTTP/2的连接存续期内始终存在,由客户端和服务器共同渐进地更新。

HTTP 2.0性能增强之TCP请求集中

TCP的优势是很直白的:面向连接、提供可靠的数据传输服务、流量控制。那么有效地使用TCP连接的方法就是长时间连接传输大块数据。于是HTTP/2就尽大化的把这一特点发扬:所有HTTP/2通信都是在一个TCP连接上完成。前面说过,HTTP/2把HTTP协议通信的基本单位缩小为一个一个的帧,这些帧对应着逻辑流中的消息,并行地在同一个TCP连接上双向交换消息(注意这个“双向交换消息”)。举个例子,请求一个页面https://www.google.com,页面上所有的资源请求都是客户端与服务器上的一条TCP上请求和响应的!

这样“单链接多资源”的方式,使到至上而下的层面都得到了好处:
1.可以减少服务链接压力,内存占用少了,连接吞吐量大了;
2.由于TCP连接减少而使网络拥塞状况得以改观;
3.慢启动时间减少,拥塞和丢包恢复速度更快。

综上所述,“资源合并减少请求”对于HTTP/2是无用的优化手段。

上面的文字说了要注意“双向交换消息”,那么啥是“双向交换消息”?

就是把HTTP消息分解为独立的帧,交错发送,然后在另一端重新组装。专业一点说就是“一个request对应一个id,这样一个连接上可以有多个request,每个连接的request可以随机的混杂在一起,接收方可以根据request的id将request再归属到各自不同的服务端请求里面”。这是HTTP/2重要的一项增强。事实上,这个机制会在整个Web技术栈中引发一系列连锁反应, 从而带来巨大的性能提升,因为:

1
2
3
4
可以并行交错地发送请求,请求之间互不影响;
可以并行交错地发送响应,响应之间互不干扰;
只使用一个连接即可并行发送多个请求和响应;
消除不必要的延迟,从而减少页面加载的时间;

paradin

Keep Alive与HTTP/2集中TCP的区别

HTTP1.1keep-alive是为了尽可能使用持久链接,以消除TCP握手和慢启动。但是keep-alive使用多了同样会给服务端带来大量的性能压力,并且对于单个文件被不断请求的服务(例如图片存放网站),keep-alive可能会极大的影响性能,因为它在文件被请求之后还保持了不必要的连接很长时间。

举个例子:下载a.js创建一个TCP链接,就会需要TCP握手和慢启动而产生了约300ms下载延迟。当a.js下载完成后这时候b.js也要下载,如果a.js创建TCP链接是keep-alive的,b.js就可以复用其TCP而不需要重新TCP握手和慢启动(没有了那300ms)。

HTTP/2是使用一个TCP链接的,其慢启动和握手只在第一次链接的时候产生一次,其后面链接都是持久化的。并且一个TCP下载多个资源,可以将TCP吞吐量最大化来提升性能,这方面可以参考一下TCP的拥塞预防及控制。
paradin

paradin

NGINX上如何配制HTTP/2

上面说了这么多HTTP/2这个好那个好,是未来的趋势blablabla,但是要实现HTTP/2,还是需要“客户端和服务器都开启了HTTP/2”这一个首要条件。不过现在客户端(浏览器)大多数都已经支持HTTP/2,那么主要就是在服务器端如何开启HTTP/2,nginx的配置方法请见:https://rorschachchan.github.io/2018/03/16/使用nginx开启http2协议/

按照这样的操作下来,服务器就开了HTTP/2协议,那些支持HTTP/2的浏览器在请求页面的时候就会走HTTP/2模式,而不支持HTTP/2的浏览器会议就按照HTTP/1.X的方式发送请求,如图:
paradin

paradin

支持HTTP/2的Web Server基本都支持HTTP/1.1。这样,即使浏览器不支持HTTP/2,双方也可以协商出可用的HTTP版本,没有兼容性问题。
paradin

参考资料

http://www.alloyteam.com/2015/03/http2-0-di-qi-miao-ri-chang/comment-page-1/#comments
https://segmentfault.com/a/1190000007637735
https://github.com/creeperyang/blog/issues/23
https://www.nginx.com/blog/nginx-1-9-5/
https://ye11ow.gitbooks.io/http2-explained/content/part6.html

-------------This article is over!Thanks for reading!-------------
感谢您请我喝咖啡!(o´ω`o)
0%