文章基调
- 不是科普类文章,不是科普 http2 性能的文章
- 记录 http2 中难以了解的点,系作者在学习 http2 时的困惑,曾经最终的了解
-
是集体的了解,可能有不谨严的中央,欢送探讨
如何了解 TCP 分帧 与 http2 分帧 的区别
- 假如「传输残缺的数据」是「运输一个订单货物」,每「订单中的一个货物」占满「一个货车厢」
-
TCP 位于传输层,能够了解为 运输的货车
- TCP 中的每一帧都是有序的,按发车工夫标记趟次,第一趟次,第二趟次,第三趟次,第 N 趟次
- TCP 能够同时发若干辆车,假如 4 辆车,则一次发车就有,第一趟次,第二趟次,第三趟次,第四趟次
- 每辆车有些提前达到,有些很慢才到,不肯定依照发车的程序达到目的地
- 当其中一个趟次的车回来了,才发下一趟车次。
- 趟次的作用,是为了货品送到目的地的时候能够从新按顺序排列,能够将每趟次的货了解为高达模型的整机(一车只运送一个整机),有程序,能力辨认从新拼装起来
- 将一个订单中的货,别离通过不同的趟次运输,就是「TCP 二进制分帧」,将订单的货(残缺的数据)分成每一车(帧)进行运输
-
HTTP 处于应用层,一个 http 申请及响应,能够了解为下订单(申请)购买一批货(响应)的过程,(留神是一批,有若干个货物 )而这批货并没有货品名称( 无奈对应这批货对应的是哪个订单,无奈将响应与申请关联起来)
- 这时 http 还没有分帧化,粒度是以订单为单位,一个订单就是一个 http
- 将一个 TCP 链接了解为一个运输合同
-
http0.9,1.0
【问题】每一次订单都签一次运输合同,很麻烦- 签一次运输合同(三次握手)
- 下订单(申请)
- 生产货物(服务器计算结果)
- 发动运输(TCP 传输内容)
- 收货物(响应)
- 结一次运输合同的账(四次挥手)
- 签一次运输合同(三次握手)
- 下订单(申请)
- 生产货物(服务器计算结果)
- 发动运输(TCP 传输内容)
- 收货物(响应)
- 结一次运输合同的账(四次挥手)
-
http1.1 keep-alive
【改良】运输合同改成月结,复用 TCP 链接
【问题】工厂无奈同时生产多个订单的货物,须要上一个订单收货- 签一次运输合同(三次握手)
- 下订单(申请)
- 生产货物(服务器计算结果)
- 发动运输(传输内容)
- 收货物(响应)
- 下订单(申请)
- 生产货物(服务器计算结果)
- 发动运输(传输内容)
- 收货物(响应)
- 结一次运输合同的账(四次挥手)
-
http1.1 pipeline
【改良】能够同时发多个订单了,通过收货程序,来辨认货物对应的是那一次订单的内容
【改良】工厂能够同时生产多个订单的货
【问题】订单存在依赖关系,即便第二次订单的货物生产好了,也得等第一次订单的货物生产好并全副传输完,能力发货。否则会被当做第一个订单的货- 签一次运输合同(三次握手)
- 下订单(第一个申请)
- 下订单(第二个申请)
- 同时生产第一个批和第二批货物(服务器计算结果)
- 按程序发第一个订单的运输(传输内容)
- 按程序收货物(响应,对应第一个响应)
- 按程序发第二个订单的运输(传输内容)
- 收货物(响应,对应第二个响应)
- 结一次运输合同的账(四次挥手)
-
http2
【改良】将一个订单的货拆分成多个批次,为每个批次标识上是哪个订单的货
【改良】因为能辨认一批次货品所属订单,最小粒度从一个订单的货,改为一批次的。本来按订单运输,当初改为按批次运输,这个最小颗粒度的变动就是 http2 分帧:将一个响应或申请拆分成多个分帧片段
【改良】最小粒度变成了批次,生产完一批次的货品,就能够马上传输,不须要等整个订单的货全副生产完才传输- 签一次运输合同(三次握手)
- 下订单(第一个申请)
- 下订单(第二个申请)
- 同时生产第一个订单和第二订单的货物(服务器计算)
- 每生产批次货物,就给这批次的货打上标签,标识是哪个订单的货(分帧)
- 筹备好了一批次货物,就发运输,不须要管是哪个订单的(传输)
- 收货,从新分拣是哪个订单的货(依据分帧标识对应是那一次申请的响应)
- 每生产批次货物,就给这批次的货打上标签,标识是哪个订单的货(分帧)
- 筹备好了一批次货物,就发运输,不须要管是哪个订单的(传输)
- 收货,从新分拣是哪个订单的货(依据分帧标识对应是那一次申请的响应)
- 直到所有货物都传输实现
- 结一次运输合同的账(四次挥手)
-
总结
- 能够看出,tcp 的分帧与 http2 的分帧是不同维度的辨别
- tcp 的分帧维度是一个趟次运输(一个趟次运输一个货物),http2 的分帧维度是 一批货物(可能是一个货物,也可能是若干个货物)
- http2 分帧的实质是将本来一个订单(一个申请或响应),拆分成多个批次(多个帧),放大数据颗粒度,减少灵活性
-
参考资料
- https://segmentfault.com/q/1010000005167289
- https://blog.csdn.net/u598975767/article/details/112788129
- https://blog.wangriyu.wang/2018/05-HTTP2.html
为什么要分帧
-
实质上,只有给一个订单的货(响应)打上订单(申请)标识,就能够标识是哪个订单的,就能够解决先订单依赖的问题(后一个订单不须要等前一个订单传输完),为什么须要将订单拆散为批次呢?
- 车的数量(TCP 通道宽度,流量宽度)是无限的,拆散了并不是放慢运输过程
- 拆成批次(分帧)是为了从本源反对数据的调配传输,如果一个订单的量很大,按订单发货,就得等整个订单的货生产实现能力运输。而拆成批次(分帧)就能够将粒度减低,生产一个批次就运输一个批次,不须要等整个订单的货生产实现。
如何了解 http1.1 是文本协定,http2 是二进制协定
- stackoverflow 中对应的探讨,对应国内论坛
-
文本协定,信息传输过程经验以下步骤
- 编写文本,因为规定比拟涣散,可能存在多余的前后空格,多余的换行等状况
- 传输文本,传输的是 ASCII,即文字对应的编码
- 读取文本,了解文本,辨认 ASCII 码组合起来的单词,再通过字符串匹配的形式匹配意义
-
二进制协定
- 这里的二进制,次要体现在两个方面「二进制帧封装」及「头部压缩」
-
「二进制帧封装」行将数据打散,外包一层二进制帧数据(用于标识以后帧的个性)
- 所以是这一分帧层进行了二进制封装,而不是 http 的内容二进制,所以更适合的称说应该是「减少了二进制分帧层」
- 这里的二进制帧数据,是用二进制为颗粒度代表数据的含意,每个 0 和 1 代表非凡的含意
- 而文本协定,是通过 ASCII 对应的单词来表白含意,
- 即代表数据的颗粒度不一样了,本来是有若干个字母,当初是由若干个比特
-
「头部压缩」
- 通过动态表和动静表的索引值来代表含意
- 相当于单方建设的长期暗号
http2 头部压缩,如何做到浏览器动静表与服务器动静表的同步
- 【疑难】因为竞速问题,在申请头未注册到服务器之前接管了另一个申请。
- 【计划】http2 在分帧中有明确规定,申请头与响应头的分帧,两头不能插入其余分帧。从而保障残缺的申请头和响应头是按程序传输的。故不会存在竞速问题。
- stackoverflow 中对应的探讨
- 在 HTTP2 中的 CONTINUATION 帧有相干的介绍,对应中文文档
- segmentfault 中对于 CONTINUATION 帧的介绍