Open vivatoviva opened 5 years ago
Http2.0出来的是解决Http1.1的问题,Http1.1存在什么问题?
Http2.0性能提升的核心就在于二进制分帧层,HTTP2是二进制协议,他采用二进制格式传输数据而不是1.x 的文本格式
http1.1响应的是文本格式,而http2.0把响应划分为两个帧,图中的Headers(首部)和DATA(消息负载)是帧的类型,也就是说一条HTTP响应,划分成两个帧来传输,并且采用二进制来进行编码
Http1.1中出现的线头阻塞和多个TCP连接的问题,Http2.0多路复用完美解决,让Http2.0所有的通信都在一个TCP连接上完成,真正实现了请求的并发
HTTP2建立一个TCP连接,一个连接上面可以有任意多个流(stream),消息分割成一个或者多个帧在流里面传输,帧传输过去以后,在进行重组,形成一个完成的请求或者响应,这使得所有的请求或者响应都无法阻塞。
头部压缩也是HTTP2的一大亮点,在1.x的版本中,首部使用文本格式传输,通常会给每个传输增加500-800字节的开销,我们发现现在打开一个网页上百个请求都是常态,而每个请求带的一些首部字段都是相同的,例如cookie、user-agent等,HTTP2为此采用HPACK压缩格式来压缩头部,头部压缩需要在浏览器和服务器之间:
所以我们在传输首部字段的时候,例如传输method:Get那么我们只需要传输静态字典中对应的索引就可以了,一个字节搞定,像user-agent、cookie这种静态字典里面的只有首部而没有值的首部,第一次传输需要user-agent在静态字典中索引以及他的值,值会采用静态Huffman编码来减小体积,第一次传输过user-agent之后,浏览器和服务器就会把他添加到自己的动态字典中,后续传输就可以传输索引了,一个字节搞定
服务器端推送使得服务器可以预测客户端需要的资源,主动推送到客户端,例如:当客户端请求index.html,服务器能够额外推送script和style,实现的原理就是客户端发出页面请求的时候,服务器端能够分析这个页面所依赖的其他资源,主动推送到客户端的缓存,当客户端收到原始网页的请求,他需要的资源已经位于缓存中。
针对每一个希望发送的资源,服务器会发送一个PUSH_PROMISE帧,客户端可以通过发送RES_STREAM帧来拒绝推送(当资源已经位于缓存)。这一步操作先于父响应,客户端了解到服务器端打算推动那些资源,就不会为这些资源创建重复请求。当客户端收到index.html的响应是,相应的资源已经位于缓存中。
通过上面这张图可以看出,长连接可以解决复用TCP连接的功能,但是还是无法解决请求阻塞问题,也就是一个请求的开始需要在等上一个请求结束才可以发起,为什么会存在这个问题,因为Http1.1是通过需要每条请求都是可识别的,按照顺序发送,否则server就不能判断相应的是哪个具体的请求。那么Http2.0中是这样解决这个问题的,在同一个域名下,开启一个TCP的connection连接,每个请求以stream的方式进行传输,每个stream有唯一的标识,connection一旦建立,后续的请求都可以复用这connection并可可以同时发送,server端可以根据stream的唯一标识对应的请求。
多路复用根据标准显示,会在下面两个时机关闭:
但是标准是这样,每个服务器都有自己的实现
Http 1.1存在的问题
Http2.0出来的是解决Http1.1的问题,Http1.1存在什么问题?
Http2.0重大改进
二进制分帧层
Http2.0性能提升的核心就在于二进制分帧层,HTTP2是二进制协议,他采用二进制格式传输数据而不是1.x 的文本格式
http1.1响应的是文本格式,而http2.0把响应划分为两个帧,图中的Headers(首部)和DATA(消息负载)是帧的类型,也就是说一条HTTP响应,划分成两个帧来传输,并且采用二进制来进行编码
多路复用
Http1.1中出现的线头阻塞和多个TCP连接的问题,Http2.0多路复用完美解决,让Http2.0所有的通信都在一个TCP连接上完成,真正实现了请求的并发
HTTP2建立一个TCP连接,一个连接上面可以有任意多个流(stream),消息分割成一个或者多个帧在流里面传输,帧传输过去以后,在进行重组,形成一个完成的请求或者响应,这使得所有的请求或者响应都无法阻塞。
头部压缩
头部压缩也是HTTP2的一大亮点,在1.x的版本中,首部使用文本格式传输,通常会给每个传输增加500-800字节的开销,我们发现现在打开一个网页上百个请求都是常态,而每个请求带的一些首部字段都是相同的,例如cookie、user-agent等,HTTP2为此采用HPACK压缩格式来压缩头部,头部压缩需要在浏览器和服务器之间:
所以我们在传输首部字段的时候,例如传输method:Get那么我们只需要传输静态字典中对应的索引就可以了,一个字节搞定,像user-agent、cookie这种静态字典里面的只有首部而没有值的首部,第一次传输需要user-agent在静态字典中索引以及他的值,值会采用静态Huffman编码来减小体积,第一次传输过user-agent之后,浏览器和服务器就会把他添加到自己的动态字典中,后续传输就可以传输索引了,一个字节搞定
服务器端推送
服务器端推送使得服务器可以预测客户端需要的资源,主动推送到客户端,例如:当客户端请求index.html,服务器能够额外推送script和style,实现的原理就是客户端发出页面请求的时候,服务器端能够分析这个页面所依赖的其他资源,主动推送到客户端的缓存,当客户端收到原始网页的请求,他需要的资源已经位于缓存中。
针对每一个希望发送的资源,服务器会发送一个PUSH_PROMISE帧,客户端可以通过发送RES_STREAM帧来拒绝推送(当资源已经位于缓存)。这一步操作先于父响应,客户端了解到服务器端打算推动那些资源,就不会为这些资源创建重复请求。当客户端收到index.html的响应是,相应的资源已经位于缓存中。
多路复用和keep alive的区别
通过上面这张图可以看出,长连接可以解决复用TCP连接的功能,但是还是无法解决请求阻塞问题,也就是一个请求的开始需要在等上一个请求结束才可以发起,为什么会存在这个问题,因为Http1.1是通过需要每条请求都是可识别的,按照顺序发送,否则server就不能判断相应的是哪个具体的请求。那么Http2.0中是这样解决这个问题的,在同一个域名下,开启一个TCP的connection连接,每个请求以stream的方式进行传输,每个stream有唯一的标识,connection一旦建立,后续的请求都可以复用这connection并可可以同时发送,server端可以根据stream的唯一标识对应的请求。
多路复用什么时候关闭
多路复用根据标准显示,会在下面两个时机关闭:
但是标准是这样,每个服务器都有自己的实现
参考的资料