# TCP队头阻塞

## TCP队头阻塞（head of line blocking）

HTTP/2是基于TCP实现的。相比之前的版本，HTTP/2使用的TCP连接数少了很多。TCP是一个可靠的传输协议，基本上，你可以将它视为在两台计算机间建立的一个虚拟链路，由一端放到网络上的内容，最终总会以相同的顺序出现在另一端。（或者遭遇连接中断）

![两台计算机间的TCP链路](https://3391341413-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LvW30M9uwlSh6noqzxa%2F-LvW31Pn1JTBepfnVcl_%2F-LvW36RhYtOh6iUIAkc1%2Ftcp-chain.png?generation=1575733990547404\&alt=media)

采用HTTP/2时，浏览器一般会在单个TCP连接中创建并行的几十个乃至上百个传输。

如果HTTP/2连接双方的网络中有一个数据包丢失，或者任何一方的网络出现中断，整个TCP连接就会暂停，丢失的数据包需要被重新传输。因为TCP是一个按序传输的链条，因此如果其中一个点丢失了，链路上之后的内容就都需要等待。

如下图所示，我们一个用链条来表现一个连接上发送的两个流（传输），红色的与绿色的数据流：

![不同颜色的链条代表着不同的链路](https://3391341413-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LvW30M9uwlSh6noqzxa%2F-LvW31Pn1JTBepfnVcl_%2F-LvW36RnZxzFY7KrlZth%2Ftcp-chain-streams.png?generation=1575733990706732\&alt=media)

这种单个数据包造成的阻塞，就是TCP上的队头阻塞（head of line blocking）。

随着丢包率的增加，HTTP/2的表现越来越差。在2%的丢包率（一个很差的网络质量）中，测试结果表明HTTP/1用户的性能更好，因为HTTP/1一般有六个TCP连接，哪怕其中一个连接阻塞了，其他没有丢包的连接仍然可以继续传输。

在限定的条件下，在TCP下解决这个问题相当困难。

## 独立的数据流避免阻塞问题

使用QUIC时，两端间仍然建立一个连接，该连接也经过协商使得数据得到安全且可靠的传输。

![两台电脑间的一条QUIC链路](https://3391341413-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LvW30M9uwlSh6noqzxa%2F-LvW31Pn1JTBepfnVcl_%2F-LvW36Rpk4cKkyV66974%2Ftcp-chain.png?generation=1575733990704266\&alt=media)

但是，当我们在这个连接上建立两个不同的数据流时，它们互相独立。也就是说，如果一个数据流丢包了，只有那个数据流必须停下来，等待重传。

下面是两个端点间的示意图，黄色与蓝色是两个独立的数据流。

![两台电脑间的两个QUIC数据流](https://3391341413-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LvW30M9uwlSh6noqzxa%2F-LvW31Pn1JTBepfnVcl_%2F-LvW35oOH4Xtr4ClEuBt%2Fquic-chain-streams.png?generation=1575733990265929\&alt=media)
