计算机网络——详解HTTP2.0"/>
计算机网络——详解HTTP2.0
HTTP2.0在前文已经提及过了,但是他调优的详细情况还没总结。
回顾一下HTTP1.1的缺点:
1.头部冗余,有重复字段或字符串
2.头部过大,传输压力大
3.队头堵塞,非管道传输请求堵塞,管道传输响应堵塞
4.必须由客户端发起连接,服务器给予相应
5.无请求优先级处理
HTTP如何处理请求头冗余:
HPACK算法
1.静态表
2.动态表
3.哈夫曼压缩
静态表
静态表的长度为61,里面记录了请求头的一些常用的字段和字符串,静态表共有三列,第一列是里面字段的索引,第二列是请求头字段的名称,第三列是请求字段的值(若为空白,那么可能是经常出现的请求字段,但是值经常不固定)。最后可以通过静态表对请求头字段进行二进制压缩。首先用一个字节,共八位,前两位用于选择状态:如果为01则是使用静态表。后六位可以组成2^6-1种结果共63种,涵盖了所有静态表字段情况。第二个字节第一位为0或1,若为1那么则表示经过哈夫曼编码,那么后续的7位则用于表示经过哈夫曼编码后字段属性的字节数。后续的字节根据7位表示的字节数来定,最后向里面填充字节属性。
动态表:
动态表一开始并不存在,但是可以在一次连接中生成,客户端和服务器端都会拥有相同的动态表。若经常发送同一字段,那么就会从静态表62索引开始追加新添加的字段及其属性。那么下次发送同一个请求时,只需要发送一个字节即可(该字节表示了自己选用的是动态表,以及多少号索引)。
动态表造成的问题:动态表需要内存存储,对于我们客户端,感知不大,但是对于服务器端,那么可能就是灾难性的,毕竟客户端与服务器是一对一,服务器对客户端是一对多。消耗大量的内存会加重服务器的负担。因此Web 服务器都会提供类似http2_max_request 的配置,用于限制⼀个连接上能够传输的请求数,避免动态表无限增⼤,请求数量到达上限后,就会关闭 HTTP/2 连接来释放内存。
二进制帧
http2.0使用二进制帧来处理响应消息,他把响应消息分为两个帧,一个为HEADERS,另一个为DATA。
HEADERS共9个字节,前三个字节用于表示帧的长度,第四个字节用于表示帧的类型,共有九个,第五个是标志位,用于表示帧的一些控制信息如:所在流的优先级,后续有没有帧。最后四位中第一位保留不用,后续31位表示所属流序号。
DATA就是用于表示响应数据,采取了和请求一样的Hpack算法(静态表+动态表+哈夫曼编码压缩)。
使用hpack算法完成了对头部的字节压缩,完成了头部冗余的复用操作,解决了http1.1两个问题。
有关帧和流
http1.1对于请求响应的传输有两种,一个是请求-响应的格式,即一次TCP连接中一个请求对应一个响应。另外一个是管道传输,即一次TCP连接中,可在前一个响应未到达前发送后续请求,最后请求按次序返回,客户端按次序将请求与响应对应起来。
无论是原始的请求-响应格式还是管道传输,http1.1视乎都是把TCP当成了两路火车,只能在两条道上实现往返。但是实际上到达对面还可以不用火车。http2.0采用了Stream,Message和Frame,一次TCP连接含有多个流,一个流中可能含有多个请求或多个响应,一个请求加响应中可能含有多个帧。多跳流可以并发传输。
还是以铁轨为例,原先的传输就像是上了年代,无论哪次连接都只能通过两地的火车进行运输,但是先不一样了,通向两地的不仅有往返的火车轨,还有高速,HTTP2.0将一个或多个请求放在了一个大的集装箱中,由一个大货车运输,但同一条高速上可不止一辆大货车,那么在传输信息的过程中,多个大货车可以一起传输,只要到地了之后把所有的货物按照车牌号卸载,然后统一管理即可。即多个请求可以不按照次序进行发送,只要流有标号,那么无论谁先到都会被放在指定的位置。这时如果发生堵塞,也就是一个请求发送接收缓慢,那么其实也就是一辆车货多了,开的慢,那么后面的货完全没必要搭乘这趟车。这就解决了http1.1中的队头堵塞问题。
需要注意的是,无论请求所属哪条流,请求内部的帧必须按照顺序发送,应为帧所属的message是没有标号的。不同的流之间的帧发送可以乱序,但是同一个流中的帧必须有序。就像高中时代排队做操一样,假设学校共有5楼,每层有4个班,那么每一层就相当于一个流,每个班就相当于一个请求或响应,每个人就是一个帧,那么早操铃一响,所有帧都会跑出来,按位置在教室门外站好,然后下楼时,楼道单一,可能你后面一个就是其他楼层的学生,但是你知道,你所处的位置一定是按照班级的位置传输的。最后到达操场指定位置,从无序又变成了有序。
帧和流首先解决了队头堵塞的问题。
其次可以给流标号,客户端的流是奇数,服务的流是偶数,有序的流还可以设置优先级,比如css和js资源的流优先传,图片视频资源的流最后传,改善了用户体验。
帧和流还解决了处理优先级的问题。
除此之外使用帧和流还能提供推送功能,当用户请求html资源时,客户端会解析请求然后在同一个流中返回一个控制帧,该帧表示是PUSH_PROMISE,并使用promise stream id字段告知客户端即将发送推送信息,位于哪个流中。
更多推荐
计算机网络——详解HTTP2.0
发布评论