HTTP2的过人之处

  • 一、HTTP1.1的高延迟性能问题
  • 二、HTTP2的针对HTTP1.1的优化
    • 兼容老版本
    • 头部压缩
      • HTTP1.1存在的问题
        • 静态表编码
          • 概述
          • 过程
        • 动态表编码
          • 概述
          • 过程
          • 使用前提
          • 不足
    • 二进制帧
    • 并发传输
      • Steam、Message、Frame之间的关系
      • StreamID
      • Stream优先级
    • 服务器主动推送资源

一、HTTP1.1的高延迟性能问题

  • HTTP头部巨大且重复
  • 对头阻塞问题
  • 不支持服务器推送消息
  • 并发连接有限

二、HTTP2的针对HTTP1.1的优化

兼容老版本

  • HTTP没有在URI里引入新的协议名,仍然用http://表示明文协议,用https://表示加密协议, 于是只需要浏览器和服务器在背后自动升级协议,这样可以让用户意识不到协议的升级,很好的实现了协议的平滑升级。
  • 只在应用层做了改变,还是基于 TCP 协议传输,应用层方面为了保持功能上的兼容,HTTP2把HTTP分解成了语义和语法两个部分,语义层不做改动,与 HTTP1.1 完全⼀致,比如请求方法、状态码、头字段等规则保留不变。 但是,HTTP/2 在语法层面做了很多改造,基本改变了 HTTP 报文的传输格式。

头部压缩

HTTP1.1存在的问题

  • 存在很多固定字段,比如Cookie、Accept等,加起来占的字节高达几百到几千,有必要进行压缩。
  • 大量的请求和报文里很多字段都是重复的,有必要避免重复性。
  • 字段是ASCII编码的,虽然易于观察,但不适合传输,有必要改成二进制编码。

HTTP2没有使用常见的gzip,而是开发了HPACK算法

  • 静态字典
  • 动态字典
  • Huffman编码(压缩算法)

客户端和服务器两端都会建立和维护字典,用长度较小的索引号表示重复的字符串,再用Huffman 编码压缩数据,可达到 50%~90% 的高压缩率。

静态表编码

概述

HTTP2为高频出现在头部的字符串和字段建⽴了⼀张静态表,它是写入到 HTTP2框架里的,不会变化的,静态表里共有61组。

过程

例如,server头部字段的Index为 54,⼆进制为110110,再加上固定01,头部格式第1个字节就是 01110110,第二个字节的首个比特位表示Value是否经过 Huffman编码,剩余的 7 位表示Value的长度,10000110,首位为1,表示 Value字符串是经过Huffman编码的,经过Huffman编码的Value长度为6。

动态表编码

概述

静态表只包含了 61 种⾼频出现在头部的字符串,不在静态表范围内的头部字符串就要自行构建动态表,它的Index从62起步,会在编码解码的时候随时更新。

过程

例如,第⼀次发送时头部中的user-agent字段数据有上百个字节,经过 Huffman 编码发送出去后,客户端和服务器双方都会更新自己的动态表,添加⼀个新的Index号62。那么在下⼀次发送的时候,就不用重复发这个字段的数据了,只用发 1 个字节的 Index号就好了,因为双方都可以根据自己的动态表获取到字段的数据。

使用前提

使用动态表的前提是:必须同⼀个连接上,重复传输完全相同的 HTTP 头部。如果消息字段在 1 个连接上只发送了1次,或者重复传输时,字段总是略有变化,动态表就无法被充分利用了。

不足

动态表越大,占用的内存也就越大,如果占用了太多内存,是会影响服务器性能的,因此Web服务器都会提供类似 http2_max_requests 的配置,用于限制⼀个连接上能够传输的请求数量,避免动态表无限增大,请求数量到达上限后,就会关闭 HTTP/2 连接来释放内存。

二进制帧

HTTP/2 把响应报文划分成了两个帧(首部,消息负载)传输,并采用二进制来编码。
首部

  • 前3个字节:代表数据帧的长度
  • 第4个字节:表示帧的类型(共有10种,一般分为数据帧和控制帧)
  • 第5个字节:标志位,用于携带简单的控制信息
    • END_HEADERS 表示头数据结束标志
    • END_STREAM 表示单方向数据发送结束,后续不会再有数据帧
    • PRIORITY 表示流的优先级
  • 最后4个字节:流标识符(StreamID),但最高位被保留不用,只有 31 位可以使用,它的作用是用来标识该 Fream 属于哪个Stream,接收方可以根据这个信息从乱序的帧里找到相同StreamID的帧,从而有序组装信息。

消息负载

  • HPACK算法压缩过的HTTP头部
  • HPACK算法压缩过的 HTTP包体
    HTTP2二进制帧结构

并发传输

Steam、Message、Frame之间的关系

  • 1个TCP连接包含⼀个或者多个Stream
  • Stream里可以包含1个或多个Message,Message对应 HTTP1中的请求或响应,由HTTP 头部和包体构成
  • Message里包含⼀条或者多个Frame,Frame 是 HTTP/2最小单位,以⼆进制压缩格式存放HTTP/1中的内容(头部和包体)
  • HTTP消息可以由多个Frame构成,以及1个Frame可以由多个TCP报文构成

StreamID

  • 不同 Stream的帧是可以乱序发送的(因此可以并发不同的 Stream ),因为每个帧的头部会携带Stream ID信息,所以接收端可以通过Stream ID有序组装成HTTP消息,而同一Stream内部的帧必须是严格有序的。
  • 客户端建立的 Stream ID必须是奇数号,而服务器建立的Stream必须是偶数号。
  • 同⼀个连接中的 Stream ID是不能复⽤的,只能顺序递增,所以当 Stream ID 耗尽时,需要发⼀个控制帧 GOAWAY ,用来关闭 TCP 连接。 在 Nginx 中,可以通过http2_max_concurrent_streams 配置来设置 Stream 的上限,默认是 128 个

Stream优先级

HTTP/2还可以对每个Stream 设置不同优先级,帧头中的标志位可以设置优先级。

服务器主动推送资源

客户端发起的请求,必须使⽤的是奇数号Stream,服务器主动的推送,使用的是偶数号 Stream。服务器在推送资源时,会通过PUSH_PROMISE帧传输 HTTP 头部,并通过帧中的Promised Stream ID字段告知客户端,接下来会在哪个偶数号Stream 中发送包体。
在Stream 1中通知客户端CSS 资源即将到来,然后在Stream2中发送 CSS 资源,注意 Stream1和2是可以并发的。

HTTP2牛逼在哪儿?相关推荐

  1. Serializable 都这么牛逼了,Parcelable 还要你何用?

    一些闲聊 距离上一篇文章似乎又是很久了,看起来也没有很多反馈,催更就更不用说了.哈哈,放弃了. 话说最近公司在招聘一批至少 5 年开发经验的 Android 开发工程师,我也是忙开了花,激动得不行呀. ...

  2. python七大神级插件_IntelliJ IDEA 15款超级牛逼插件推荐(自用,超级牛逼)

    满满的都是干货  所有插件都是在 ctrl+alt+s   里的plugins 里进行搜索安装 1.CodeGlance 代码迷你缩放图插件 2. Codota 代码提示工具,扫描你的代码后,根据你的 ...

  3. 最牛逼的 Java 日志框架,性能无敌,横扫所有对手.....

    欢迎关注方志朋的博客,回复"666"获面试宝典 来源:juejin.cn/post/6945753017878577165 Logback 算是JAVA 里一个老牌的日志框架,从0 ...

  4. 放弃 Notepad++,事实证明,还有 5 款更牛逼……

    点击关注公众号,Java干货及时送达 今天跟大家聊一聊,作为文本编辑工具,还有比 Notepad++ 更好的替代工具吗?别说,还真有另外5款(为啥有些粉丝说,要卸载Notepad++ 呢,其实这个No ...

  5. 早就听闻阿里开源的 Arthas 在做 Java 应用诊断上十分牛逼,没失望

    点击上方蓝色"方志朋",选择"设为星标"回复"666"获取独家整理的学习资料! 来源 | https://jitwxs.cn/a64edcb ...

  6. 太牛逼了!项目中用了Disruptor之后,性能提升了2.5倍

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! ‍存储设备往往是速度越快价格越昂贵,速度越快价格越低廉.在 ...

  7. 我终于决定要放弃 okhttp、httpClient,选择了这个牛逼的神仙工具!贼爽

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 在SpringBoot项目直接使用okhttp.httpC ...

  8. 虽然这些代码很少,就几行,但却很牛逼!

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 作者:编程艺术思维 来源:urlify.cn/jqUree ...

  9. 卸载Notepad++!事实已证明,它更牛逼……

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 作者:lucida lucida.me/blog/subl ...

最新文章

  1. SPPNet网络结构
  2. 人人直播带货的时代,推荐模型为什么比不过李佳琦们?
  3. 你必须非常努力,才可以看起来毫不费力。
  4. label y 训练集测试集x_Adversarial validation-对抗验证| 一种解决训练集与测试集分布不一致的方法...
  5. mysql列增减_Mysql基本操作——增减改查
  6. mysql管理节点_MySql节点管理安装步骤需要在SerA和SerB上各做一次
  7. php列表框怎么用,PHP+Mysql+jQuery查询和列表框选择操作实例讲解
  8. 别再Prompt了!谷歌提出tuning新方法,强力释放GPT-3潜力!
  9. ansible 模块_您需要了解的Ansible模块
  10. 在IIS6上部署MVC2网站(续篇)
  11. python round保留小数位_Python-其他-round()保留小数位时遇到的问题
  12. 打开Android Studio报错“Error running ***: Please select Android SDK”
  13. python爬虫requests库_python爬虫基础教程:requests库(二)代码实例
  14. java变量练习_Java变量与运算符练习
  15. mysql密码字段_如何在mysql中创建带有密码字段的表?
  16. MFC中CString.Format的详细用法
  17. 谷歌、bing 翻译插件调研总结
  18. 计算机后台处理程序,小编教你处理打印后台程序服务没有运行
  19. 熵增定律与人际关系-整理
  20. 【概率论与数理统计(研究生课程)】知识点总结4(随机变量的数字特征)

热门文章

  1. 中国空间站:无缘登月中转站,却是技术试验场
  2. ##**iOS蓝牙开发(一)蓝牙相关基础知识**
  3. 我所知道坦克大战(单机版)之解决坦克出界问题、添加机器坦克、将机器坦克击毙...
  4. dict转json保存_14、序列化操作,类的保存和dict转JSON
  5. ubuntu 16.04 ATI显卡 radeon VCE init error (-22)
  6. 计算机网络面试题【面试】
  7. 【漏洞学习——越权】e家洁某处存在越权漏洞
  8. 想要成为一名软件开发人员?这个职业道路指南可以了解下
  9. 盘点:10款适合创业团队使用的团队协作工具
  10. 耳下长包图片_耳锤下面长了个硬包是怎么回事