Persistent vs Non-persistent Connection(持续连接与非持续连接)

Definition

非持续连接(Non-persistent Connection)持续连接(Persistent Connection) 是应用层协议(如 HTTP)管理和复用底层 TCP 传输层连接的两种核心方式。

它规定 / 它负责:

  • 非持续连接:每个请求/响应对都使用一个独立的 TCP 连接,交互完成后立即关闭连接。
  • 持续连接:多个请求/响应共享并复用同一个已经建立好的 TCP 连接,避免频繁建立与销毁连接。

简单理解:

非持续连接是“一次买卖一建连”,持续连接是“建立通路多次传输”。


核心内容 / 模式对比

1. 非持续连接 (Non-persistent Connection)

HTTP/1.0 的默认通信方式。

特点:

  • 1 请求 = 1 TCP 连接:客户端请求每一个 Web 对象(如 HTML 页面、图片、CSS 文件)都需要重新发起 TCP 三次握手。
  • 高响应时延:每个对象的传输都需要额外的 1 RTT 建立 TCP 连接,外加 1 RTT 的 HTTP 请求/响应传输时间。
  • 频繁挥手与慢启动:每个新 TCP 连接都需要重新经历 TCP 慢启动(Slow Start)过程,拥塞窗口未能在多次请求间得到充分积累。

2. 持续连接 (Persistent Connection / Keep-Alive)

HTTP/1.1 开始默认启用的通信方式;连接通常保持复用,除非通过 Connection: close 等方式显式关闭。

特点:

  • 多请求 = 1 TCP 连接:服务器在发送响应后保持 TCP 连接打开,后续请求继续沿用该连接。
  • 节省时延:后续对象传输无需重新握手,节省了连接建立的 1 RTT 时延。
  • 高带宽利用率:TCP 拥塞窗口(cwnd)在同一个连接中得到维持和增长,传输效率显著提升。

系统位置 / 交互机制

应用层发起数据传输时,底层 POSIX Socket 和 TCP 协议栈的交互过程差异如下:

flowchart TD
    N1["非持续连接: 三次握手"] --> N2["读写请求/响应"] --> N3["四次挥手释放"]

    P1["持续连接: 三次握手"] --> P2["请求 1 / 响应 1"] --> P3["请求 2 / 响应 2"] --> P4["超时关闭"]

底层系统行为解析:

  1. 非持续连接:服务端为每个请求调用 accept() 返回一个新的已连接 Socket (fd),数据发送完毕后服务端或客户端调用 close();主动关闭连接的一端可能积累大量 TIME_WAIT 状态连接,消耗端口等系统资源。
  2. 持续连接:服务端保持已连接 Socket (fd) 处于可读/可写状态,应用层多次读取 HTTP 请求包并写入响应,直至达到 keepalive_timeout(空闲超时)或 keepalive_requests(连接最大请求数)上限。

核心对比与设计权衡

对比维度非持续连接 (Non-persistent)持续连接 (Persistent)
TCP 握手开销高(每次请求 1 次三次握手)低(仅首个请求需要握手)
传输时延高(每个对象增加 1 RTT 握手时延)低(无额外握手时延)
服务器 Socket 资源占用短(连接迅速释放回收)较长(需占用 Socket / 内存直至超时)
高并发下的风险容易产生大量 TIME_WAIT 端口耗尽空闲连接过多时消耗服务端内存与句柄
典型协议代表HTTP/1.0 默认HTTP/1.1 默认

演进与局限:队头阻塞 (Head-of-Line Blocking)

虽然 HTTP/1.1 持续连接避免了重复握手,但引入了著名的 队头阻塞 (HOL Blocking) 问题:

1. HTTP/1.1 队头阻塞的产生原因

  • 在 HTTP/1.1 **流水线(pipelining)**中,同一个持续 TCP 连接上的响应必须按照请求发送的先后顺序(FIFO)返回。若客户端逐个等待响应,持续连接本身并不会产生并行响应的队头阻塞。
  • 典型场景:当多个请求被流水线发送到同一连接时,前一个大对象的响应传输会阻塞后续小对象的响应,即使后续请求已经处理完成,也必须等待前一个响应完成。
flowchart TD
    Big["大对象视频 (传输中 / 独占连接通道)"] -- "队头阻塞 (HOL)" --> Small1["小文件 1 (挂起等待)"]
    Small1 -- "顺序等待" --> Small2["小文件 2 (挂起等待)"]

2. HTTP/1.1 的无奈妥协

为了缓解流水线队头阻塞,浏览器历史上常对同一域名建立多个并行 TCP 连接,常见实现曾以约 6 个连接为上限;这属于客户端实现策略,不是 HTTP/1.1 的统一标准要求,也会增加客户端端口与服务端 Socket 资源消耗。

3. HTTP/2 与 HTTP/3 的进一步改进

  • HTTP/2 二进制分帧(Binary Framing & Multiplexing):HTTP/2 将不同的 HTTP 请求/响应拆成带有 Stream ID 的帧,在单条 TCP 连接上交错传输,各流内部仍保持顺序,从而消除了 HTTP/1.1 流水线的应用层队头阻塞。
  • HTTP/3 (QUIC):HTTP/2 仍受 TCP 字节流队头阻塞影响;HTTP/3 使用基于 UDP 的 QUIC,为各流提供独立的可靠、有序交付,从而避免 TCP 字节流层面的跨流队头阻塞。

Summary

持续连接通过复用 TCP 连接消除了握手与慢启动开销;但 HTTP/1.1 按序响应的特性导致了队头阻塞(HOL Blocking)。HTTP/2 通过二进制分帧多路复用突破了这一限制。

核心关键词:

  • TCP 复用 (TCP Reuse)
  • RTT 时延 (RTT Latency)
  • 保持连接 (Keep-Alive)
  • 队头阻塞 (Head-of-Line Blocking)
  • 二进制分帧 (Binary Framing)

Related Concepts(关联概念)