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域名的原因。
http2.0
这是一个演示,演示了HTTP/2对您下载构成Akamai旋转地球仪的许多小互动程序的影响。
可以看出http2.0要比http1.1快很多。http2.0相比于http1.1做了一下的改进:
- 二进制分帧
- 多路复用
- 头部压缩
- 服务器推送
二进制分帧:
http2.0解决并发的主要手段就是这个二进制分帧。
通俗的讲,http1.1是基于文本传输的(请求行、请求头、请求主体)
在http2.0中,位于应用层和传输层之间加了个二进制分帧层,文本数据会被分割成更小数据块(数据帧),二进制编码。其中首部会被封装在HEADRE frame中,body被封装在DATA frame中。
大致的数据结构如下:
通过stream indentifier来识别这个数据帧属于数据流的哪一块,然后根据块号来组装成一个完整的数据,http就可以并发请求了。
多路复用:
以打开一个网页为例子:
- 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可以让连接不断开
- 首先这个不断开也不是永久的,一般有时间间隔,比如超过300s,没请求,就断开。
- 这个keepalive只是针对同一个域名下,访问同一个静态文件多次请求可以复用。
- 即使可以复用,多个请求也只能是串行处理,因为是基于文本传输的,只能顺序传输
- 对于不同的文件无能为力,只能再次建立连接
- 多路复用可以针对不同的文件,复用同一个连接,并且得益于二进制分帧的数据传输,可以并行。
头部压缩:
1. 静态字典:
一个请求中,请求头往往也占用了很大一部分开销,特别对于请求头特别大的。但是往往有些请求头是比较静态的东西,比如method:GET,对于这种比较固定的东西,双方可以用更简化的方式来表示。这就是静态字典:
像method:GET 可以用一个数字2表示。
2. 动态字典:当key、value都是固定的,我们可以用静态字典,但是当key是静态的,value是动态的(比如cookie),这时候就要依赖动态字典了,核心就是哈夫曼编码(出现概率较大的采用较短的编码)。
总结:静态字典+动态字典+哈夫曼编码,通过较少的数据量可以完成较大数据量的传输。
服务器推送:
正常的一个请求,我们是分别请求html和css的,那么就要发起多次请求。当有了服务端推动,就可以根据请求的html,把对应的css、js文件一起发给客户端,省的客户端再次发起请求。