一个 TCP 连接发送多个 HTTP 请求,省去反复握手开销——这就是连接复用的核心思想。用动态图一步步搞懂它。
每次 HTTP 请求都要新建一个 TCP 连接,用完立刻关闭。请求 3 个资源就要 3 次完整握手和 3 次挥手。
HTTP/1.1 默认开启 Keep-Alive,一个 TCP 连接可以连续发送多个请求,无需重复握手。请求 3 个资源只需要 1 次握手!
连接复用的能力在不同 HTTP 版本中不断增强。HTTP/2 的多路复用真正解决了队头阻塞(HTTP 层面),HTTP/3 则用 QUIC 从传输层根除了这个问题。
现代 HTTP 客户端默认启用连接复用。看几个典型场景。
// 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}
# -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 的本质就是:响应完之后不关闭 TCP 连接,等一段时间看还有没有新请求。超时就关掉。