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["超时关闭"]
底层系统行为解析:
- 非持续连接:服务端为每个请求调用
accept()返回一个新的已连接 Socket (fd),数据发送完毕后服务端或客户端调用close();主动关闭连接的一端可能积累大量TIME_WAIT状态连接,消耗端口等系统资源。 - 持续连接:服务端保持已连接 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)