前言
队头阻塞(Head-of-Line blocking, 简写:HOL blocking), 是http相关协议的一个著名问题, 它会导致延时的提高. 队头阻塞, 是指第一个数据包(队头)受阻而导致整列数据包传输受阻. 队头阻塞在OSI的多个层中都有, 那么有哪些队头阻塞呢?
- HTTP队头阻塞
- TLS队头阻塞
- TCP队头阻塞
1、应用层-HTTP队头阻塞
1.1 什么是HTTP队头阻塞
http协议是基于TCP协议的. 在http1.0中, http队头阻塞是指:
在同一个TCP通道上, 客户端的第一个http请求, 会阻塞该客户端后续的http请求, 直到客户端接收完毕第一个http请求的响应
http1.0中, 请求1发出后, 不能立即发出请求2, 要等响应1收到后, 才能发出请求2.
http1.0已经不大使用了, 目前常用的http版本是http1.1, 在http1.1中, http队头阻塞是指:
在同一个TCP通道上, 服务端的第一个http响应, 会阻塞服务端后续的http响应, 直到服务端发送完毕第一个http响应
http1.1使用了pipeline技术, 解决了http1.0中的客户端队头阻塞, 使得客户端请求可以连续发出, 然而仍然存在服务端的队头阻塞, 响应的顺序必须和请求的顺序保持一致.
1.2 如何应对HTTP队头阻塞
http队头阻塞的原因, 是因为http协议设计上, 不支持响应的乱序. http的请求和响应是一一对应的, 要支持响应的乱序, 需要能够根据响应反推出是哪个请求,
应对方式: 请求和响应都带上同一个唯一ID
于是, 在http2中, 增加了streamId, 一对请求和响应, 会带有同一个streamId.
wireshark抓包, http2获取icon_wechat.png, 请求中带有streamId 3, 对应的响应也是streamId 3.
这种本质上是做异步的协议, 类似的设计还有mongo, 请求中带有requestId, 响应中带有responseTo, 值就是requestId
2、会话层-TLS队头阻塞
2.1 什么是TLS队头阻塞
https中的s, 代表了SSL/TLS协议, TLS协议是SSL协议的演进版本, 目前常用的TLS1.2和TLS1.3. TLS协议, 位于http协议和TCP协议之间. TLS会对发出的数据进行加密, 对收到的数据进行解密, 问题是, TCP会根据MSS(Maximum Segment Size ,TCP提交给IP层最大分段大小)进行分包,
发出时, TLS对发出的完整数据加密, 而TCP会把TLS加密后的数据进行分包, 接收时, TLS要等待完整的数据都收到后, 才能进行解密, 然后把解密后的数据交给应用层.
TLS队头阻塞是指:
在同一个TCP通道上, 接收端, 要等待组成完整数据的所有TCP包, 都接收完毕后, TLS才可以进行解密
2.2 如何应对TLS队头阻塞
QUIC的解决思路是这样的: 应用层分包, 然后对每个包单独进行加密
加解密会消耗CPU资源, 对每个包单独加解密, 解决了TLS队头阻塞的延时, 但是带来了频繁加解密的延时, 在低丢包率的网络上, 这个方案并不会有效降低延时. TLS协议是为了保障数据安全, 为了安全, 这个延时开销省不了.
3、传输层-TCP队头阻塞
3.1 什么是TCP队头阻塞
TCP队头阻塞, 既包含了发送端的队头阻塞, 也包含了接收端的队头阻塞. TCP发送端队头阻塞是指:
在同一个TCP通道上, 第一个TCP滑动窗口内的多个分组, 在全部发送且ack确认完成前, 会阻塞后续的滑动窗口的发送
TCP接收端队头阻塞是指:
在同一个TCP通道上, 如果sequence number较小的包丢失了, 则后续sequence number较大的包都会积压在接收端缓存中, 且无法被应用层获取到.
3.2 如何应对TCP队头阻塞
TCP协议本身也在尝试缓解这个问题, 例如, 快重传, SACK重传, 但是, 并未解决.
应对方式: 换传输层协议
总结
本文介绍了http相关的多种队头阻塞, 以及相关的应对.
|