HTTP2新特性与Nginx布署

发布:elantion 日期:2018-07-11 阅读:1828 评论:0

很多人会很好奇,现在网速已经快到惊人了,为什么打开一个网页仍需要那么长时间?其实除了网页内容不断增长之外,还有一个很重要的原因,就是现在的HTTP 1.1协议实在是太慢了,该协议已经近十多年没更新了,至到2015年HTTP 2才定稿。

HTTP 1.1那里不好?

后浪推前浪是历史的必须发展规律,所以HTTP 2的出现表示现在HTTP 1.1肯定有不足的地方,但其实最大的问题就是慢。现在的宽带一般都有10M,一秒至少能传1MB左右的内容,一个网页一般也就1MB到2MB,理论上来说1-2秒就能下载完,宽带不应该是制约网页打开速度的原因。但现实是网页的打开速度远远不止1-2秒,能在两秒内打开已经是相当好的成绩,看看百度首页的加载时间(HTTP/1.1):

只加载200kb的内容,却使用了近一秒的时间,宽带并没有完全利用起来。就像水管很粗,但没有用满整支水管。

队列阻塞

HTTP是基于TCP/IP的协议,所以当需要下载一个网页时,必须通过TCP的握手协议建立通道,然后才可以下载网页。但每条通道里要下载的文件是要排队的,例如某条通道里需要下载一张图片和一个JavaScript文件,如果图片在队列前面,那么浏览器就会等图片下载完之后才会下载那个JavaScript文件。如果图片下载途中卡住了,那个JavaScript就不能下载了。所以现在很多浏览器会加开几条通道以防『塞车』。但多通道还有另外一个好处就是:使文件可以同时下载,以尽可能利用宽带。就像多开几条水管,同时传输。

延迟

上面说到浏览器会开多通道,但每建一条通道都必须握手一次,握手时TCP需要在客户端和服务端咨询一个来回,我们叫Round time trip(RTT)。所以通道越多,RTT需要的时间越多,就这会产生明显的延迟。就像我们家里需要新增水管时,你得跑自来水公司办理一样,这延迟是很可观的。

重复的头部信息

由于HTTP是无状态的协议,意思是说服务器和客户端都不会保留对方的信息,所以双方每次都需要把完整的信息告诉对方。就像快递公司并不会记录你的信息,它们只会按照快递单的地址、收件人来投递,每次投递都必须填写完整的信息。例如你每天都需要往同一个地方发快递,每次都要填同样的信息,会不会觉得很烦?HTTP也一样,客户端每次都必须告诉服务器我的浏览类型、支持的编码方式,或者服务器每次都必须告诉客户端文件的编码方式,这些都是多余的重复的信息。特别是现在的头部信息越来越大,尤其是需要cookie记录信息的,那更是可观,造成的宽带浪费更明显。

HTTP 2解决的痛点

HTTP 2可以说是针对HTTP 1.1的各个痛点进行改革,除了上面几个显著的改进之外,还增加了几个非常有意思的特性。

帧传输

HTTP 2使用了帧传输机制,就像TCP/IP协议的原理一样,把文件拆为几个帧,然后写上编号,对方接收到之后就按编号还原文件。有了这种机制之后,HTTP只需利用一条通道就同时发送多个文件,而且可以不用排队传输,因此也就不会产生阻塞。而且由于编号可以分隔双方的帧,因此就可以双向通信,例如客户端在接收图片时,还可以同时发送请求给服务器。这种帧传输机制称之为Multiplexed streams(有人译为多路复用,但我更喜欢『帧传输』),就像用火车运输火箭,需要把火箭拆解,到发射地之后再重新组装起来,这样不仅可以同时运输多支火箭,还可以顺便运输汽车,之间并不影响。有了这种机制,HTTP就不需要开多个通道,延迟大大降低,也不会产生队列阻塞问题。

权重标签

想象一下,如果页面有非常多图片,并且使用了图片懒加载机制,当用户把窗口滑到某图片位置时,浏览器就会向服务器请求加载该图片。如果用户滑动很快,好几个图片滑过去了,更论上来说,滑过去的图片权重应该要低一些,当前展示的图片应该更高,服务器应该优先返回当前图片。然而HTTP 1.1却不这么认为,谁先请求,谁就优先返回。所以,当用户使用HTTP 1.1浏览长页面时,你只能求神拜佛:用户别滑太快了。这是不现实的,所以HTTP 2在帧上加了权重标签,权重越高,越先加载。所以你就不必担心用户滑动过快的问题了。
权重标签还可以标示依赖关系,例如某个JavaScript的运行时必须依赖某个JavaScript,那么就可以往被依赖的JavaScript的帧上贴上依赖,这样执行顺序就不会错了。

停止帧

HTTP 1.1不能直接停止某个文件的下载,当发送了Content-Length,就必须完整地下载完整个文件,除非把TCP通道断了,但重新打开会很耗时。HTTP 2针么这个问题,设计出停止帧RST_STREAM frame,当发送一个停止帧就可以暂停某个文件的下载,可以节省不少的流量。

头部压缩

还记得上面寄快递的例子吗?每次发送请求都附上一堆重复的头部信息是否很多余?到了HTTP 2,你只把不一样的头部信息发送就可以了,在多请求的网站可以节省不少宽带。

其他

除了以上的重要功能之外,还有流量控制、二进制传输、服务器推送等有意思的功能。更重要的是,HTTP 2可以降级为HTTP 1.1,因此你不必担心升级了HTTP 2协议而丢失大批用户。

HTTP 2的评论

虽然HTTP 2解决了很多HTTP 1.1的问题,但它是否就是完美呢?我们看看常见的一些评论:

必须结合HTTPS使用?

不完全对,IETF说HTTP 2是可以不使用HTTPS使用的,但实际上大浏览器厂商却表示不可以,例如Chrom、FireFox,他们说是为了安全和用户体验,确实,HTTP 2配合HTTPS『食用』是最好的,因为HTTP 2在HTTPS创建安全通道过程中就可以顺便完成HTTP 2的选择,既有HTTPS的安全,也有HTTP 2的高效。可能有人会问HTTPS不是很慢么?其实通过优化,用户是感知不到那种差距的,更何况HTTPS安全性的提高,那点小损失算得了什么。而且由于HTTP 2单通道的特性,无疑更适合HTTPS。

HTTP 2是Google的协议?

看过HTTP 2的历史的同学应该知道:HTTP 2其实就是SPDY(Google的HTTP协议)的演化版本,甚至决定HTTP 2协议的成员很多都是Google的员工,这不禁让人怀疑这是否Google的黑箱操作?但Google很明确地说,You can you up。确实目前来说,这没有更好的方案了。然鹅,Google已经计划开发更牛逼的协议(QUIC)了,估计下个HTTP 3也由Google来主导了?我大Google技术碾压,让别人无话可说。。。

HTTP 2仅适合大型网站?

这视乎升级的成本和收益了,小型网站使用HTTP 2也可以得到更好的用户体验(高速、低延迟、推送等),只是效果没有大型网站来得更明显,所以只是个值不值的问题,而不是好不好的问题。像本站已经使用了HTTP 2,不知道大家有没有感知什么不同?

其它

还有一些问题,例如HTTP 2只是改进了HTTP 1.1 ,没有做到革命性的改变。HTTP 2只是在HTTP 1.1下加了一层,增加了复杂度,等等。这些问题,HTTP 2都可以给出合理的解释,但这些只是技术上的问题,更重要的是用户的返馈,我们适目以待。

Nginx配置

Nginx配置HTTP2非常简单,只要在配置文件加上http2的标记就可以了,参考下面的配置,但不要全照抄。

server {
    listen 443 ssl http2;
    server_name www.lazycoffee.com;
    ssl_certificate /path/to/your.pem;
    ssl_certificate_key /path/to/your.key;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_prefer_server_ciphers on;
    ssl_ciphers HIGH:!aNULL:!MD5;
    location / {
        proxy_pass http://localhost:3000;
    }
}

之所以开启HTTPS是因为大多数浏览器仅支持HTTPS下的HTTP2。

布署过程中常见问题

  1. ssh版本太旧,导致HTTP2握手失败,退回1.1协议。解决办法:升级最新版本openSSH(至少支持ALPN握手协议),重新编译新版的Nginx,重启系统(我服务器重启后才生效,奇怪。。。)即可。
  2. 新版Nginx不再支持SPDY。解决办法:放弃SPDY(推荐)或使用Tengine之类软件替代Nginx。
  3. 抛弃旧的HTTP1.1优化手段。例如使用多域名增加TCP通道。

如果想了解更详细的布署过程,请参考:Nginx+Node.js+HTTPS+HTTP2布署

Google的新玩意:QUIC

看完上面,大家可能想到:HTTP2只是在HTTP 1.1下再加了一层TCP协议,像帧传输、流量控制等,都是借鉴了TCP的特性,因此Google脑洞一开,既然多了一层,那索性把底层的TCP去掉吧,于是诞生了QUIC。这个新协议简单来说,就是UDP + TLS + HTTP 2,UDP协议相比TCP,它更简单高效,它不用创建通道,不用校验数据,没有流量控制等一堆TCP的特性,显得不可靠,但也因此相当高效。QUIC把这些TCP特性交给HTTP 2去实现了,因此保证了可靠性。
QUIC并没有改变HTTP之前的特性,例如头部信息还是一样的结构和作用,所以我认为这只是HTTP 2的一个小升级,或许只是个"HTTP 2.5"版本。但HTTP今后不再有次版本升级,没有HTTP 2.1、2.5等,下一版本只会是HTTP 3,所以QUIC很可能只会是Google接SPDY后又一个『玩具』。

参考

http2 explained: https://http2-explained.haxx.se/content/ -- Daniel Stenberg