http2为什么那么快

1,625 阅读4分钟

http协议有三次比较重大的改革,分别是1.0、 1.1、 2.0

http1.x

  • http1.0比较久远,缺点比较明显:短链接,每次请求都必须三次握手,且第二个请求必须等待第一个请求响应返回了,才能发起。
  • http1.1相比http1.0多了个pipline,多个请求的话,可以排队串行发过去,客户端还是得按照请求的顺序来接收,如果一个响应超时,后面的请求就得排队,这种叫做线头阻塞(HOLD)。当然http1.1也做了像304这样的缓存优化,当一个文件未发生改变时,就不用去请求服务端了。
    浏览器对于HTTP/1.1在同一域名下的并发请求限制了数目: | 浏览器 | HTTP 1.1 | | --- | --- | | IE 6, 7 |2 | IE 8, 9 |6 | Firefox 13 |6 | Chrome 20 |6 | Safari 5.1.7 |6 | Opera 11.64 |8

这也是为什么一些页面如果需要加载很多图片用了多个cdn域名的原因。 image.png

http2.0

WX20210613-182540@2x.png 这是一个演示,演示了HTTP/2对您下载构成Akamai旋转地球仪的许多小互动程序的影响。
可以看出http2.0要比http1.1快很多。http2.0相比于http1.1做了一下的改进:

  • 二进制分帧
  • 多路复用
  • 头部压缩
  • 服务器推送

二进制分帧
http2.0解决并发的主要手段就是这个二进制分帧。 906e22193e61cd561325d93aae0f1e07_1440w.jpg
通俗的讲,http1.1是基于文本传输的(请求行、请求头、请求主体) carbon (2).png 在http2.0中,位于应用层和传输层之间加了个二进制分帧层,文本数据会被分割成更小数据块(数据帧),二进制编码。其中首部会被封装在HEADRE frame中,body被封装在DATA frame中。
大致的数据结构如下: image.png
通过stream indentifier来识别这个数据帧属于数据流的哪一块,然后根据块号来组装成一个完整的数据,http就可以并发请求了。
多路复用
以打开一个网页为例子:
image.png

  • http1.1,请求,响应,请求,响应,connection closed
  • http2.0,请求 * 2,响应 * 2,connection alive。 可以看出http1.1在页面渲染完后,连接就断了,下次请求页面的时候,还是得从建立连接开始。http2.0 首先可以并发的请求,并且server端可以并发响应,结束后,连接不会断。即使一个请求卡住了,也不会影响下一个请求。这样一个连接可以被多个请求使用。
    相比http1.1,http2.0可以不用频繁创建连接,多个请求可以公用一个TCP连接,这种优化可以最大限度的利用带宽。即使给足http1.1足够的带宽,它也不能做到低延迟。

那多路复用和http的keepalive有啥区别? http有keepalive,我们知道开启这个keepalive可以让连接不断开

  1. 首先这个不断开也不是永久的,一般有时间间隔,比如超过300s,没请求,就断开。
  2. 这个keepalive只是针对同一个域名下,访问同一个静态文件多次请求可以复用。
  3. 即使可以复用,多个请求也只能是串行处理,因为是基于文本传输的,只能顺序传输
  4. 对于不同的文件无能为力,只能再次建立连接
  5. 多路复用可以针对不同的文件,复用同一个连接,并且得益于二进制分帧的数据传输,可以并行。

头部压缩
1. 静态字典
一个请求中,请求头往往也占用了很大一部分开销,特别对于请求头特别大的。但是往往有些请求头是比较静态的东西,比如method:GET,对于这种比较固定的东西,双方可以用更简化的方式来表示。这就是静态字典

WX20210614-092252@2x.png 像method:GET 可以用一个数字2表示。
2. 动态字典:当key、value都是固定的,我们可以用静态字典,但是当key是静态的,value是动态的(比如cookie),这时候就要依赖动态字典了,核心就是哈夫曼编码(出现概率较大的采用较短的编码)。
总结:静态字典+动态字典+哈夫曼编码,通过较少的数据量可以完成较大数据量的传输。

服务器推送

image.png 正常的一个请求,我们是分别请求html和css的,那么就要发起多次请求。当有了服务端推动,就可以根据请求的html,把对应的css、js文件一起发给客户端,省的客户端再次发起请求。