直接检查后端响应头是否含connection: keep-alive且无connection: close,并结合ss命令验证established连接数是否稳定,可快速确认后端是否支持keepalive;若不支持,将导致nginx频繁建连、time_wait堆积、延迟升高和cpu上升。

直接看后端响应头和连接复用行为,就能快速确认是否因不支持 keepalive 导致性能下降。核心问题是:Nginx 发起了长连接请求,但后端返回 Connection: close 或根本没回 keep-alive 头,导致每次请求都重建 TCP 连接——建连开销、TIME_WAIT 堆积、延迟升高、CPU 上升,这些现象背后往往就是这个原因。
检查后端响应头是否含 keep-alive
用 curl 直连后端服务,重点观察响应头:
-
必须出现
Connection: keep-alive(大小写不敏感),且不能同时出现Connection: close - 可选但推荐有
Keep-Alive: timeout=XX, max=YY,说明后端明确支持并配置了 keepalive - 如果响应头里只有
Connection: close,或压根没Connection字段(HTTP/1.0 默认行为),就说明后端未启用 keepalive
命令示例:curl -I http://backend:8080/health
注意加 -I 只取响应头,避免干扰判断。
验证 TCP 连接是否真正复用
连续发多次请求,看底层 TCP 连接是否复用:
- 先执行
ss -tnp | grep :8080记下当前后端端口的 ESTABLISHED 连接数(比如是 1) - 再用
curl http://backend:8080/api/test执行 5 次 - 再次执行
ss -tnp | grep :8080,如果连接数仍为 1,说明复用成功;如果变成 5 或持续增长,说明每次都在新建连接
更直观的方法:在第二次请求时加 -v 看 curl 输出,若提示 * Connection #0 to host backend left intact,表示连接被保留;若出现 * Closing connection,则已被关闭。
对比 Nginx 日志中的 upstream_addr 和连接数
开启 Nginx access log 的 $upstream_addr 和 $upstream_connect_time 字段:
- 如果大量请求的
$upstream_connect_time明显大于 0(比如 >5ms),尤其在低并发下也频繁出现,说明频繁建连 - 如果
$upstream_addr中同一后端地址反复出现192.168.1.10:8080, 192.168.1.10:8080, ...(逗号分隔多个相同地址),代表 Nginx 不得不为每个请求新建连接 - 配合
ss -tnp | grep nginx | grep ESTAB | wc -l查 Nginx 到后端的总连接数,若远超upstream keepalive N设置值(如设了 32,却看到 200+ ESTABLISHED),基本可断定 keepalive 未生效
常见后端框架的 keepalive 默认状态
不同后端默认行为差异大,容易踩坑:
-
Tomcat:默认开启 keepalive(
connectionTimeout=20000),但若在server.xml中显式设了disableUploadTimeout="true"或覆盖了 connector 配置,可能意外关闭 -
Spring Boot(Tomcat):默认开启,可通过
server.tomcat.connection-timeout=20000控制;若用 Undertow,默认也开,需配server.undertow.keep-alive-timeout -
Node.js http.Server:默认
keepAliveTimeout = 5000(5 秒),极易比 Nginx 的空闲超时还短,造成 RST;建议显式设为 30000 或更高 -
Python Flask / uWSGI:Flask 内置开发服务器默认不支持 keepalive;uWSGI 需开启
--http-keepalive或配置http-keepalive = true
只要后端未明确启用并调优 keepalive,Nginx 单方面配置 keepalive 32 和 proxy_http_version 1.1 就只是“一厢情愿”,性能不会提升。











