HTTP/1.1 的队头阻塞问题是什么?

HTTP/1.1 的队头阻塞问题由请求按顺序处理引起,导致后续请求响应延迟。解决方案包括使用多个 TCP 连接和域名分片。

网络协议 困难 HTTP 性能优化 HTTP/1.1

HTTP/1.1 的队头阻塞问题是指当一个 TCP 连接上维护多个请求的复用机制导致首个请求处理变慢时,后续所有请求都无法及时接收响应的现象,主要由于 HTTP/1.1 协议的管道化(pipelining)特性限制造成:

  1. 根本原因与机制
    • HTTP/1.1 支持复用持久连接,但由于其明文协议特征,请求和响应需按严格顺序处理,不能并行处理或混合顺序。如果客户端同时启用多个连接或同一域名下允许多个请求加入连接(即管道化),请求能被批量发送但响应仍须依发送顺序严格返回。例如,如果一个资源响应被延迟接收(如下载延迟),后续关联资源的响应就被强制性阻塞无法获取。
    • 服务器逻辑处理中必须按照 HTTP/1.1 的要求按照写入时顺序处理与响应写入到连接之中。在连接复用中不能做到中断前请求去响应别的请求请求。
  2. 性能影响
    • 此特性阻碍 web 加载效能,使重要资源不能提前返回影响视觉可见用户。页面延迟明显恶化用户的首次页面启动时间指标(FCP),特别是在高资源数的现代单页应用(SPA)中明显可测试观察到响应时间异常。
  3. 当前在 HTTP/1.1 层面的解决措施
    为适应 HTTP/1.1 无法有效解决此问题而提出下列解决方法:
    • 并发 TCP 连接(Concurrent Connections): 浏览器自身行为绕过序问题允许单一域名可以允许多个 TCP 连接被发起并行处理。如 Chrome默认一次启动6个,不同浏览器支持不同数:
      // Chrome 中的连接限制数默认为6,可在 network panel 验证。
      

      增加并行处理有效减少队头问题。

    • 域名分片法(Domain Sharding):通过多个子域名处理,服务器接受分多域请求实现并行下载资源。若一个域名如 example.com,可拆分至三个或多像 static1.example.comstatic2.example.com, DNS指向同一服务器并分散载图资源请求:
      // 代码示例,用域名分散资源请求地址
      <img src="https://cdn1.site.com/img.png" alt="Image 1">  
      <img src="https://cdn2.site.com/img.png" alt="Image 2">  
      
  4. HTTP/2 / HTTP/3 的针对性替代手段与延续解法
    • HTTP/2 引入数据层传输架构使一TCP连接多复用资源块帧(frames)分别对应不同流标识符发送请求数据分割方式处理,各分针交错重新排序列处理解决 HTTP request层级堵塞 方法为:
      请求发送模型如下:  
        客户端发送 => Frame[Stream ID=1], Frame[Stream ID=2], ...
        服务器返回 => 帧根据其 ID 组成所需响应
      

      底层 TCP 数据段若乱序丢失影响帧重新组序列时可能让阻塞延迟在 TCP 维度重现即所谓 TCP 层级队头阻塞 (TCP Head-of-Line Blocking)仍无法解决。

    • 引入 HTTP/3协议利用 QUIC UDP协议来完全规避类似 TCP段结构导致的序列和确认延迟,使帧可脱离传输队首瓶颈。