企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
## **多路复用** 在HTTP/2中,有两个非常重要的概念:帧(frame)和流(stream)。 **1、帧(frame)** HTTP/2中数据传输的最小单位,因此帧不仅要细分表达HTTP/1.x中的各个部份,也优化了HTTP/1.x表达得不好的地方,同时还增加了HTTP/1.x表达不了的方式。 每一帧都包含几个字段,有length、type、flags、stream identifier、frame playload等,其中type代表帧的类型,在HTTP/2的标准中定义了10种不同的类型,包括上面所说的`HEADERS` frame和 `DATA` frame。此外还有 `PRIORITY`(设置流的优先级) `RST_STREAM`(终止流) `SETTINGS`(设置此连接的参数) `PUSH_PROMISE`(服务器推送) `PING`(测量RTT) `GOAWAY`(终止连接) `WINDOW_UPDATE`(流量控制) `CONTINUATION`(继续传输头部数据) **2、流(stream)** “流”在HTTP/2中是一个逻辑上的概念,就是说在一个TCP连接上,我们可以向对方不断发送一个个的消息,这里每一个消息看成是一帧,而每一帧有个stream identifier的字段标明这一帧属于哪个“流”,然后在对方接收时,根据stream identifier拼接每个“流”的所有帧组成一整块数据。我们把HTTP/1.x每个请求都当作一个“流”,那么请求化成多个流,请求响应数据切成多个帧,不同流中的帧交错地发送给对方,这就是HTTP/2中的多路复用。 ![](https://box.kancloud.cn/2015-10-27_562ee2c9f1375.jpg) 从上图我们可以留意到: * 不同的流在交错发送; * `HEADERS` 帧在 `DATA` 帧前面; * 流的ID都是奇数,说明是由客户端发起的,这是标准规定的,那么服务端发起的就是偶数了。 多路复用让HTTP连接变得很廉价,只需要创建一个新流即可,这不需要多少时间,而在HTTP/1.x时代却要经历三次握手时间或者队首阻塞等问题。而且创建新流默认是无限制的,也就是可以无限制的并行请求下载。不过,HTTP/2还是提供了 `SETTINGS_MAX_CONCURRENT_STREAMS` 字段在 `SETTINGS` 帧上设置,可以限制并发流数目,标准上建议不要低于100以保证性能。 优化Web性能有一个常用的技术,就是图片延迟加载,目的是除了节省流量外,还能避免图片资源与其他重要的脚本资源竞争下载。 HTTP/2提供了流的优先级与依赖性这种机制,可用 `HEADERS` 帧或 `PRIORITY` 帧设置,不过协议并没有提供如何处理优先级的具体算法,这可由服务器灵活应对。我用个例子来说明这个机制。 ~~~ <!-- a.html --> <html> <body> <script src="a.js"></script> <img src="a.jpg"> <img src="b.jpg"> <link rel="stylesheet" type="text/css" href="style.css"> </body> </html> ~~~ 浏览器是边下载边解析的,文档解析器首先遇到a.js,它就会去下载并且阻塞页面,同时,资源探测器会继续向下扫描,发现a.jpg、b.jpg和style.css并服务器发起请求。在没有优先级机制时,a.jpg、b.jpg会跟重要的a.js、style.css竞争下载,但在HTTP/2中,浏览器可以给a.jpg、b.jpg设置较低的优先级,另外依赖关系为 ![](https://box.kancloud.cn/2015-10-27_562ee2ca08fcd.jpg) 这样服务器根据优先级信息,首先吐出a.js、style.css,再吐出图片,因此页面在没有图片的情况下提前进入可交互状态。例子所说的是在浏览器层面上harcode的一个优先级策略,再比如上文提到的prefetch就可以给一个更低的优先级。在代码层面上,也许之后会提供一些控制优先级的特性,类似于目前只有IE支持的lazyload attribute。