# 6. http2为什么更快

## background

1.1相比于1来说:

* \[顺序化] 的请求使用长链接来避免产生频繁的握手/拥塞控制适应期
* \[非顺序化的请求] 的请求跟1一样还是并发的启动

另外你可能知道我们在1.1里面有一个pipeline模式, 但实际如果启用遇到比如我们之前曾经说的head-of-line blocking等问题, 因此不太常使用它. 除此之外二者在通行模式上差别不是特别大.

如下图所示, 假设我们想要并发的请求三个文件, 下面二者分别是在常规模式/piplining模式下的通讯过程, 其中管道模式的问题之前我们已经介绍过了

![](https://366761671-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MC_ucxnzAClkrgsGdFP%2Fsync%2F7c28d737eb8194fe67ea9cd7cba3d710db5c83a8.png?generation=1606716403703688\&alt=media)

![](https://366761671-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MC_ucxnzAClkrgsGdFP%2Fsync%2F0192777e3f0ff018654405ef92791ad6b49e07b5.png?generation=1606716406777291\&alt=media)

## introduction

![](https://366761671-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MC_ucxnzAClkrgsGdFP%2Fsync%2F1f6f718da4005293daacaa1d646e5c1d9509dd24.png?generation=1606716402506260\&alt=media)

我们还是以上面的请求为例, 我们现在需要发两个请求, 在上面的图中, 最直观的区别就是现在出现了两个新概念, \[stream] 以及 \[frame]

* **流**就是一个请求,  或者一个响应, 比如你发给服务器的GET请求, 如果你现在有两个HTTP请求想要发送给服务器, 你就会生成两个流
* **帧**就是这个请求的一部分, 我们把我们的几个请求打碎成帧, 然后这些帧作为TCP管道里的最小单元流淌在管道里, 如上图所示, 来自不同流的帧一起发过去, 一个请求可以这样被打碎:
  * HTTP请求的HEADER作为第一帧
  * HTTP请求的BODY作为第二帧

![](https://366761671-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MC_ucxnzAClkrgsGdFP%2Fsync%2F87dbfe92dfca693980425ccf6a419018c886a457.png?generation=1606716405666527\&alt=media)

上面那是一个HTTP2抓包示范, 1号流代表了服务器的响应, 我们请求css文件, 服务器做出的HTTP响应被当成了一个流, 1号流被分成了两个帧, 第一个帧是Header帧, 里面有HTTP响应的Header, 第二个帧是Data帧, 象征了css文件本体, 并且135号流的帧是交替混在一起发过来的

## 为什么折腾呢?

你已经知道了HTTP请求还是那些请求, 只是被打碎成帧发过去了, 现在请问这是为什么. 想要了解为什么要设计出 "流" 的概念:

1. 你需要了解为什么Pipelining为什么不被大规模使用 →&#x20;
2. 因为如果第一个延迟了, 第二个第三个都响应不了 →&#x20;
3. 因为客户端不知道哪个resp对应哪个req, 他只知道顺序 →
4. 因为HTTP请求没有序号的概念

好, 答案已经出来了, 因为没有序号, 所以没法把响应与请求对应上, 这才导致了2号3号的延迟, 很巧, 这个我们有, 因此在HTTP2里我们就能先回复2号跟3号, 这种谁先好谁就先回复的行为, 我们在HTTP2里叫它 **Multiplexing**

![](https://366761671-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MC_ucxnzAClkrgsGdFP%2Fsync%2F8aeda45946536d67968b5dc1abe50a1f54054b23.png?generation=1606716404502743\&alt=media)

## http2的其他特性

* server push: 这点有点像websocket, 服务器可以主动给客户端发送消息, 一般出现在这种场景下, 比如客户端索要 index.html , 我除了发 index.html以外, 还可以主动给你发 main.js/css 等, 你拿到了以后先缓存着, 等等你就用上了
* header compress: 这种做法的背景是我们都知道HTTP能帮你通过比如gzip压缩, 但是本质上还是只压缩了Body,  而现实中大量请求都没什么body, 只有Header, 因为HTTP是没有状态的因此Header需要反复发送, 且不能压缩. 在H2里面常用的Header名被一个index(数字)所指代, 第一次发送的时候需要带上值, 后面发送的时候只用这个数字就可以了

![](https://366761671-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MC_ucxnzAClkrgsGdFP%2Fsync%2F75b7c140acd40a35844ea1e44aa1e6fe233326c1.png?generation=1606716402661855\&alt=media)

## 本质还是HTTP1的模式

HTTP2虽然玩了很多花样, 但是无论如何离不开HTTP里面通过Header做注解, Body传数据的这种玩法, 也就是说对于服务端而言, 协议本身没有变过, 处理方式也没变过, 唯一变化的还是传输过程, 传输方式没有变过.
