Skip to content

模块导航: 总入口 · 总纲与方法 · 后端场景 · AI与算法工程 · 国企与金融 · 网络问答


15. 长连接与短连接 / keep-alive(热度 221 · 进阶) ​

Q: HTTP 长连接和短连接是什么?Connection: keep-alive 有什么行为?

A:

概念与行为 ​

  • 短连接: 每个请求建一次 TCP(三次握手),响应后关闭(四次挥手)。HTTP/1.0 默认。
  • 长连接: 同一 TCP 上串行复用多个 HTTP 请求/响应。HTTP/1.1 默认 keep-alive(除非显式 Connection: close);HTTP/1.0 需双方显式开启。
  • HTTP/2/3: 连接更持久,且多路复用/独立流,keep-alive 并入连接生命周期管理。

行为细节 ​

  1. 空闲超时与最大请求数: Keep-Alive: timeout=N, max=M;Nginx 对应 keepalive_timeout、keepalive_requests。
  2. 谁关闭: 达到 timeout/max、错误或显式 close 时,通常由服务器发起关闭。
  3. 竞态: 服务端关闭时客户端可能正在发下一条请求 → 可能失败;HTTP 允许对幂等方法重试。
  4. TIME_WAIT 分布: 谁主动关闭谁 TIME_WAIT;长连接可显著减少服务端 TIME_WAIT。

设计动机 ​

  • 减少建连开销: 每个短连接 1 RTT(TCP)+ 可能的 TLS 握手;页面数十资源时代价巨大。
  • 减少 TIME_WAIT/端口压力: 高 QPS 服务端尤其实惠。
  • 为何仍不能解决队头阻塞: HTTP/1.1 长连接上请求仍需串行/有限并发,应用层队头阻塞仍在;HTTP/2 多路复用才是根治(传输层见 HTTP/3)。

常见追问 ​

追问 1:keep-alive 省了什么?没省什么?

  • 答题要点: 省了重复 TCP(及 TLS)握手 RTT 与状态维护成本;没省单次请求的服务端处理时间,也没解决 HTTP/1.1 应用层队头阻塞。

追问 2:长连接会不会耗尽服务器资源?

  • 答题要点: 会。空闲连接占 fd/内存;需 timeout、max requests、连接数限制、LB 超时对齐。大量 CLOSE_WAIT 则是应用没关 socket 的 bug(见第 18 题)。

追问 3:客户端如何配合长连接?

  • 答题要点: 连接池复用、不要每请求新建;尊重 Connection: close;对连接被服务端关断的请求做幂等重试;监控连接错误率。

易错点 ​

易错说法纠正
「keep-alive 是 HTTP/2 新特性」HTTP/1.1 已默认;1.0 需显式开启
「长连接=WebSocket」不同:长连接仍是 HTTP 请求-响应复用;WS 是全双工帧协议
「长连接一定更快」有首字节慢/阻塞时仍可能排队;资源未复用时收益有限
「TIME_WAIT 多就关 keep-alive」通常应加强连接复用,而不是更碎地开关连接
「Connection 头对 HTTP/2 语义完全相同」HTTP/2 连接管理不同,hop-by-hop 头处理有专门规则

与选择题对照 ​

  • 主库 150: 第 145 题(Connection: keep-alive 含义)、第 84 题(HTTP 特点含持久连接)、第 92 题(HTTP 演进)、第 60/62/63/138 题(挥手与状态,长连接影响 TIME_WAIT/CLOSE_WAIT)。
  • 补题 16: 无直接 keep-alive 题。
  • 口述联动: 选择题直接考头字段含义;面试要连接池、超时竞态、与多路复用的关系。

工程 / 抓包背景 ​

  • Nginx:
    nginx
    keepalive_timeout 65s;
    keepalive_requests 1000;
    # 上游连接池
    upstream backend { server 127.0.0.1:8080; keepalive 32; }
    location / { proxy_pass http://backend; proxy_http_version 1.1; proxy_set_header Connection ""; }
  • curl: 多次请求看是否复用连接(-w 计时;verbose 可见 Re-using existing connection)。
  • ss: 对比 ss -tan 中 ESTABLISHED 与 TIME_WAIT 数量变化。
  • Wireshark: 观察多条 HTTP 请求是否在同一 TCP stream(tcp.stream eq N)。
  • 客户端: OkHttp/Go http.Client/Java HttpClient 连接池默认行为不同,需统一超时。

持续学习,持续积累。