← 返回目录

HTTP 2.0

第 103 / 154 卷日期:

如果值相等,则返回 304 Not Modified,不会返回资源;

如果不相等,则返回 200 状态码和返回资源,并在 Response 头部加上新的 ETag 唯一标识;

如果浏览器收到 304 的请求响应状态码,则会从本地缓存中加载资源,否则更新资源。

ETag(响应头)、If-None-Match(请求头)

强ETab

强ETag值,不论实体发生多么细微的变化都会改变其值。

弱ETag

弱ETag值只用于提示资源是否相同。只有资源发生了根本改变,产生差异时才会改变ETag值。这时,会在字段值最开始处附加W/,'W/'(区分大小写)开头表示使用弱校验。

对于两个资源,强校验要求每个字节都相同才认为是同一个资源;而弱校验则把决定权交给开发者,根据需要区分的要素来生成相应的 ETag。

为什么要区分强弱呢,因为大多数情况下,确保严格的字节级别的一致性是没有必要的。例如,如果我们开启了 HTTP 压缩,那么对于一个资源的响应,压缩前和压缩后的字节就是不一致的,但通常我们只关心压缩前的 ETag

,这时就需要使用弱校验的 ETag。

两者对比

如果 HTTP 响应头部同时有 Etag 和 Last-Modified 字段的时候, Etag 的优先级更高,也就是先会判断 Etag 是否变化了,如果 Etag 没有变化,然后再看 Last-Modified。

  1. 精确度:ETag>Last*Modified。ETag按照内容给资源上标识,可准确感知资源的变化。Last*Modified不一

样

编辑了资源文件,但内容没改变,会造成缓存失效 Last_Modified可感知的时间单位是s,若在1s内修改了文件,不能体现出来。

  1. 性能上:LastModified优于Etag。LastModified只是记录一个时间点,ETag根据文件具体内容生成哈希值。

协商缓存这两个字段都需要配合强制缓存中 Cache-control 字段来使用,只有在未能命中强制缓存的时候,才能发起带有协商缓存字段的请求。

HTTP 2.0

特性

HTTP/2 协议基于 HTTPS

HTTP2.0可以说是SPDY的升级版本,与SPDY的区别如下:

  1. HTTP2.0支持明文HTTP传输,而SPDY强制使用HTTPS。
  2. HTTP2.0消息头压缩算法使用HPACK,而SPDY使用DEFLATE。

HTTP2.0主要目标是改进传输性能,实现低延迟和高吞吐量。

HTTP2.0升级改造需要考虑:

  1. HTTP2.0完全兼容HTTP1.x,对于不支持HTTP2.0的浏览器,NGINX会自动向下兼容

二进制分帧

HTTP/2 不再像 HTTP/1.1 里的纯文本形式的报文,而是全面采用二进制格式,头信息和数据体都是二进制,统称为帧(frame):头信息帧(Headers Frame)和数据帧(Data Frame)。

对人不友好,但是对计算机非常友好,因为计算机只懂二进制,收到报文后,无需再将明文的报文转成二进制,而是直接解析二进制报文,这增加了数据传输的效率

(因为是新增的二进制分帧层,所以叫2.0)

不改变HTTP语义,HTTP方法、状态码、URL及首部字段。改进传输性能,实现低延迟和高吞吐量

HTTP1.x解析基于文本,文本展现形式多样,要做到健壮性考虑的场景必然很多,二进制则只有0和1,更高效健壮

首部压缩

HTTP/2 会压缩头(Header)如果同时发出多个请求,他们的头是一样的或是相似的,那么,协议会消除重复的部分

HPACK算法:在客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,以后就不发送同样字段了,只发送索引号,这样就提高速度

HTTP 1.x无首部压缩,Gzip只对请求体压缩

SPDY和HTTP 2.0都支持首部压缩。使头部帧最大程度复用,减少头部大小,利于减少内存和流量

比如:第一次请求,包含头部各种信息,后来又发送另外请求,发现大部分字段可以复用,一次只发送一个当前请求特有的头部帧即可

首部表在HTTP 2.0的连接存续期始终有效,server和client共同更新

避免重复header传输,又减少需要传输的大小

  1. HTTP2.0会压缩首部元数据,在client和server使用首部表跟踪和存储之前发送的健值对,对于相同数据,不

需每次请求响应都发送

  1. 所有header必须全部小写,而且请求行要独立为健值对(即header+值)

多路复用

HTTP 1.0:建立连接请求数据完毕之后立即关闭连接;

后来采用keep-alive模式使得可以复用连接而不断开,可利用这次连接继续请求数据

缺点:必须等到server返回上一次的请求数据才可以进行下一次请求

Q:遇到一个请求很久没有响应,后面的请求只能等待?

HTTP/2 是可以在一个连接中并发多个请求或回应,而不用按照顺序一一对应。

多路复用(MultiPlexing),即连接共享,每一个request都是用作连接共享机制的。每一个request对应一个id,一个连接上可以有多个request,每个连接的request可以随机的混杂在一起,接收方根据request的id将request再

归属到不同服务端请求里面。客户端只需要一个连接就可以加载一个页面

举例来说,在一个 TCP 连接里,服务器收到了客户端 A 和 B 的两个请求,如果发现 A 处理过程非常耗时,于是就回应 A 请求已经处理好的部分,接着回应 B 请求,完成后,再回应 A 请求剩下的部分

优点:

  1. 并行交错发送请求,请求之间互不影响
  2. TCP连接一旦建立可并行发送请求
  3. 消除不必要延迟,减少页面加载时间
  4. 可最大程度利用HTTP 1.x

请求优先级

server根据流的优先级控制资源分配,响应数据准备好后,把优先级最高的帧发送给client。browser发现资源时立即分派请求,指定每个流的优先级,让服务器决定最优的响应次序,这时请求不用排队,节省时间,最大限度利用

连接

流量控制

流:不改变协议,允许采用多种流量控制算法

特点:

  1. 流量基于HTTP连接的每一跳进行,不是端到端控制
  2. 流量基于窗口更新帧进行,接收方可广播准备接收字节甚至对整个连接要接收的字节数
  3. 流量控制有方向,接收方根据自身情况控制窗口大小
  4. 流量控制可由接收方禁用
  5. 只有data帧服从流量控制,其他不会消耗控制窗口的空间

服务端推送

HTTP/2 在一定程度上改善了传统的「请求 - 应答」工作模式,服务不再被动响应,也可以主动向客户端发送消息

server push通过推送那些它认为客户端将会需要使用到的内容到客户端缓存中,以此避免往返的延迟

  1. 客户端可以限定推送流的数量,也可以设置为0而完全禁用server push
  2. 所有推送遵守同源策略,即服务器不能随便将第三方资源推送给客户端,必须是经过双方确认的
  3. PUSH_PROMISE帧:所有服务器推送流都通过PUSH_PROMISE发送,服务端发出有意push所述资源的信

号,客户端接收到PUSH_PROMISE帧后,也可以拒绝这个流

  1. 服务端必须遵循请求-响应的循环,只能借着对请求的响应推送资源。
  2. PUSH_PROMISE帧必须在返回响应之前发送,否则客户端会出现竞态条件。

数据流

HTTP/2 的数据包不是按顺序发送,同一个连接里面连续的数据包,可能属于不同回应。因此,必须要对数据包做标记,指出它属于哪个回应

在 HTTP/2 中每个请求或相应的所有数据包,称为一个数据流(Stream)。每个数据流都标记着一个独一无二的编号(Stream ID),不同 Stream 的帧可以乱序发送(因此可以并发不同Stream),因为每个帧的头部会携带

Stream ID 信息,所以接收端可以通过 Stream ID 有序组装成 HTTP 消息

客户端和服务器双方都可以建立 Stream, Stream ID 也有区别,客户端建立的 Stream 必须是奇数号,而服务器

HTTP/2 通过 Stream 的并发能力,解决了 HTTP/1 队头阻塞的问题,看似很完美了,但是 HTTP/2 还是存在“队头阻塞”的问题,只不过问题不是在 HTTP 这一层面,而是在 TCP 这一层。

HTTP/2 是基于 TCP 协议传输数据,TCP 是字节流协议,TCP 层必须保证收到的字节数据完整且连续,这样内核才会将缓冲区里的数据返回给 HTTP 应用,当「前 1 个字节数据」没有到达时,后收到的字节数据只能存放在内核

缓冲区里,只有等到这 1 个字节数据到达时,HTTP/2 应用层才能从内核中拿到数据—— HTTP/2 队头阻塞问题。

图 198-1
图 198-1

图中发送方发送了很多个 packet,每个 packet 都有自己的序号,可以认为是 TCP 的序列号,其中 packet 3 在网络中丢失了,即使 packet 4-6 被接收方收到后,由于内核中的 TCP 数据不连续,于是接收方的应用层无法从内核

中读取,只有等到 packet 3 重传后,接收方的应用层才可以从内核中读取到数据——HTTP/2 的队头阻塞问题,发生在 TCP 层面

所以,一旦发生了丢包现象,就会触发 TCP 重传机制,这样在一个 TCP 连接中的所有的 HTTP 请求都必须等待这

全站分卷索引 · 154 卷
  1. 1代码随想录知识星球精华(最强八股文)第五版(前端篇))
  2. 2html语义化
  3. 3src 和 href 的区别
  4. 4link 与 @import 的区别
  5. 5iframe
  6. 6CSS
  7. 7伪元素和伪类
  8. 8block,inline,inline-block
  9. 9重排、重绘和合成
  10. 10盒子模型
  11. 11margin 合并
  12. 12margin和padding 的值为百分比时
  13. 13浮动
  14. 14定位
  15. 15CSS选择器
  16. 16CSS选择器优先级
  17. 17选择器权重Specificity
  18. 18CSS属性继承
  19. 19不可/可继承属性
  20. 20display: none与 visibility: hidden的区别
  21. 21background-size
  22. 22client、offset&scroll
  23. 23CSS3新特性
  24. 24flex布局
  25. 25常见布局
  26. 26三栏布局
  27. 27垂直居中
  28. 28水平垂直居中
  29. 29CSS画三角形
  30. 30使chrome支持12px以下文字
  31. 31响应式布局
  32. 32媒体查询
  33. 33过渡与动画
  34. 34JavaScript 动画 和 CSS动画
  35. 35SCSS
  36. 36CSS性能优化
  37. 37有哪些数据类型
  38. 38判断数据类型
  39. 39类型转换
  40. 40parseInt&parseFloat
  41. 41浮点数求和步骤
  42. 42十进制小数转二进制
  43. 430.1+0.2 为什么不等于 0.3
  44. 44undefined 和 undeclared 的区别
  45. 45JavaScript NaN 属性
  46. 46isFinite()&isNaN()
  47. 47数组
  48. 48对原数组有影响
  49. 49对原数组无影响
  50. 50数组去重
  51. 51数组拍平
  52. 52ES6新增的数组方法
  53. 53判断是否存在某个值
  54. 54arguments为啥不是数组
  55. 55对象
  56. 56遍历对象的方法
  57. 57判断对象是否具有属性
  58. 58for in 和 for of 的区别
  59. 59继承方式
  60. 60instanceof
  61. 61深浅拷贝
  62. 62freeze属性
  63. 63函数
  64. 64函数柯里化
  65. 65函数的 length
  66. 66箭头函数和普通函数区别
  67. 67构造函数
  68. 68执行上下文
  69. 69作用域
  70. 70作用域和作用域链
  71. 71闭包和内存泄漏
  72. 72this
  73. 73关于 this 的指向问题
  74. 74改变this指向的方法(bind / call / apply)
  75. 75字符串
  76. 76DOM和事件
  77. 77哪些事件支持冒泡
  78. 78阻止冒泡
  79. 79HTMLCollection、NodeList
  80. 80dom.onclick 和 dom.addEventListener的区别
  81. 81e.target和e.currentTarget
  82. 82页面生命周期
  83. 83异步
  84. 84内存管理GC
  85. 85其它
  86. 86JavaScript 中日期时间格式转换
  87. 87input和object实现双向绑定
  88. 88JSON.stringify()
  89. 89escape、encodeURI&encodeURIComponent
  90. 90移动端滚动穿透和溢出
  91. 91ES6
  92. 92Map字典
  93. 93... 与rest
  94. 94proxy
  95. 95模块化
  96. 96Ajax、Fetch和Axios
  97. 97Webpack
  98. 98浏览器:事件循环
  99. 99浏览器内核
  100. 100浏览器同源策略
  101. 101输入URL回车后发生了什么
  102. 102HTTP
  103. 103HTTP 2.0
  104. 104浏览器存储
  105. 105鉴权
  106. 106Webstorage
  107. 107浏览器执行机制
  108. 108AST 抽象语法树
  109. 109性能优化
  110. 110CSS
  111. 111网络相关
  112. 112使用HTTP2.0
  113. 113图片
  114. 114CDN图片
  115. 115其他文件优化
  116. 116降低APP首页开屏渲染时间
  117. 117页面白屏
  118. 118HTTPS中间人攻击
  119. 119Web Worker
  120. 120Service Worker
  121. 121微前端
  122. 122Vue
  123. 123v-show 和 v-if 的区别
  124. 124双向数据绑定的原理
  125. 125Vue中的插槽使用
  126. 126Vue中的key
  127. 127Vue过滤器
  128. 128Vue中Scoped原理
  129. 129Vue中$nextTick的使用
  130. 130Vue中实现组件通信的方式
  131. 131Vue-router
  132. 132Vue路由传参
  133. 133前端路由
  134. 134Vuex
  135. 135虚拟DOM
  136. 136DIFF 算法
  137. 137Vue3和Vue2有哪些区别
  138. 138说一说你对React的理解
  139. 139React事件机制
  140. 140说一说你对react refs的理解
  141. 141react中key的作用
  142. 142组件开发
  143. 143有状态组件和无状态组件
  144. 144函数式组件和类组件的区别
  145. 145PureComponent&Component
  146. 146常见 Hooks
  147. 147状态管理
  148. 148redux toolkit
  149. 149React18新特性
  150. 150client中的createRoot取代以前的ReactDOM.render
  151. 151Suspense
  152. 152新的Hooks
  153. 153VDom一定更快吗
  154. 154Fiber