HTTP2.0中的二进制帧层原理

前言

Http2.0中涉及到一个二进制帧层,而OSI网络模型中有一个数据链路层,数据链路层的协议数据单元也叫做帧。然而两者并不是同一个东西,Http2.0是运行在TCP传输层之上的应用层。Http2.0中的二进制帧层其实可以看做是基于传输层和应用层之间的一个分层。

Http1和Http2

Http1.0 每一次请求都必须创建一个新的TCP连接。
Http1.1 下一次请求可以沿用上一次请求的TCP连接,但是请求之间是串行的,必须等上一个请求结束后,下一个请求才能发起。
Http2.0 可以将多个请求同时在一个TCP连接中发出。

原理

TCP层传输,是将上一层协议的数据分割成多个不同序号的报文进行传输,通过滑动窗口协议和一些ACK、Syn等字段进行全双工通信(两端需要对传输报文序号进行确认,双向通信,信道冲突时候可能会采用csma/cd等算法进行处理)。

Http1.1 直接将字符形式的请求报文交付给TCP层进行传输,在应用层必须解析出请求head和body才能完成通信。

Http2.0 将应用层的数据经过二进制帧层处理,将不同的请求拆成不同的stream,由stream的id进行标记,请求的stream被分割成多种类型的帧,其中包括head帧和data数据帧。正是因为有了stream的id标记、以及各种不同类型的帧,确保了请求和响应的有序重组。

例如请求a.js和b.css,a.js对应的stream的id为1,b.css对应的stream的id为2,a.js的head帧为head1,数据帧为data1,b.js的head帧为head2,数据帧为data2。浏览器可以将head1、data1、head2、data2同时放入TCP信道进行报文传输,在TCP层,可能会进一步对这些数据进行拆分,拆成不同报文序号进行传输,但是可以无需关注这层是如何拆分、组装的。因为可以在Http2.0的二进制帧层进行有序处理,将接收到的stream的id为1的放一起处理,接收到的stream的id为2的放一起处理。

通过这种方式就可以解决Http1.1中存在的请求阻塞问题,试想:假如a.js的处理很慢,服务器可以先将b.css的处理结果返回,因为采用了stream的id编号,所以可以在Http2.0的二进制帧层先对b.css的stream的id进行重组,将b.css的响应交付于应用层处理。

总结

Http2.0 引入了一个二进制帧层,将并发的请求转成不同的stream流传输,每个stream的分帧都带有特定的序号id,这就保证了请求响应的数据可以在二进制帧层进行重组,即使传输过程是无序的。