HTTP 连接复用

一个 TCP 连接发送多个 HTTP 请求,省去反复握手开销——这就是连接复用的核心思想。用动态图一步步搞懂它。

没有连接复用时 HTTP/1.0

每次 HTTP 请求都要新建一个 TCP 连接,用完立刻关闭。请求 3 个资源就要 3 次完整握手和 3 次挥手。

每次请求需要:TCP 三次握手 + 数据传输 + 四次挥手
点击「播放动画」查看无复用时的请求过程
开启连接复用 HTTP/1.1 Keep-Alive

HTTP/1.1 默认开启 Keep-Alive,一个 TCP 连接可以连续发送多个请求,无需重复握手。请求 3 个资源只需要 1 次握手!

只需 1 次 TCP 握手,后续请求直接复用连接
点击「播放动画」查看 Keep-Alive 复用连接的过程
6 RTT
无复用 · 3 次请求
2 RTT
有复用 · 3 次请求
67%
延迟降低
连接数减少

❌ 无连接复用 (HTTP/1.0)

  • 每个请求都要 TCP 三次握手(1.5 RTT)
  • 每次响应后都要 TCP 四次挥手
  • 大量短连接导致 TIME_WAIT 状态堆积
  • 端口耗尽,无法发起新连接
  • TLS 握手也要重复执行

✅ 连接复用 (HTTP/1.1 Keep-Alive)

  • 只需一次 TCP 握手,后续请求直接发送
  • 请求结束后连接保持打开
  • 大幅减少 TIME_WAIT 连接数
  • TLS 会话也可以复用
  • 服务端更容易做连接管理和限流
连接复用的演进 HTTP/1.1 → HTTP/2 → HTTP/3

连接复用的能力在不同 HTTP 版本中不断增强。HTTP/2 的多路复用真正解决了队头阻塞(HTTP 层面),HTTP/3 则用 QUIC 从传输层根除了这个问题。

HTTP/1.1 管道化 (Pipelining) 理论上可以连续发送,但必须按顺序接收 → 队头阻塞 请求 1 → 请求 2 → 请求 3 → ← 响应 1 ← 响应 2 ← 响应 3 ⚠ 队头阻塞 响应 1 慢 → 2,3 等待
HTTP/2 多路复用 (Multiplexing) Stream 分帧并行 → 一个连接上多个请求交错传输 Stream 1 HEADERS DATA帧×N RESP Stream 2 HEADERS DATA帧×M RESP Stream 3 HEADERS DATA帧×K RESP ✓ 无队头阻塞 各 Stream 独立 交错传输、独立接收
HTTP/3 (QUIC) 基于 UDP 的 QUIC 协议,传输层也消除队头阻塞,连接迁移无需重新握手 0-RTT / 1-RTT 连接迁移(Connection ID) 无传输层队头阻塞
代码中的连接复用

现代 HTTP 客户端默认启用连接复用。看几个典型场景。

Go Go net/http 默认启用 Keep-Alive
// Go 的 http.Transport 默认 MaxIdleConns=100, MaxIdleConnsPerHost=2
// 同一个 host 的请求会自动复用空闲 TCP 连接
resp1, _ := http.Get("https://api.example.com/users")
resp2, _ := http.Get("https://api.example.com/orders")
// resp1 和 resp2 很可能共用同一个 TCP 连接

// 自定义 Transport 可以调整复用参数
tr := &http.Transport{
    MaxIdleConns:        100,
    MaxIdleConnsPerHost: 10,  // 每个 host 最多保持 10 个空闲连接
    IdleConnTimeout:     90 * time.Second,
}
client := &http.Client{Transport: tr}
curl 用 curl 观察连接复用
# -v 显示详细过程,可以看到 "Re-using existing connection"
curl -v https://api.example.com/a https://api.example.com/b

# 输出中会出现:
# * Re-using existing connection! (#0) with host api.example.com
# * Connected to api.example.com (1.2.3.4) port 443 (#0)
核心机制:Keep-Alive 怎么工作的?

Keep-Alive 的本质就是:响应完之后不关闭 TCP 连接,等一段时间看还有没有新请求。超时就关掉。

客户端 服务端 GET /page HTTP/1.1 200 OK + Connection: keep-alive 连接空闲等待中... GET /style.css HTTP/1.1(复用同一连接!) 200 OK + Connection: keep-alive 空闲超时 → 关闭连接 FIN
HTTP 连接复用 · 动态图解 · 2026