CentOS 7.9 的 nginx 到后端之间开了 upstream keepalive,后端 Tomcat 的 keepAliveTimeout 只有五秒,每天上午零星出现 502,错误日志写 upstream prematurely closed connection。

一开始怀疑是「两边的空闲超时不一致,后端先关,nginx 后知后觉」,查了一圈,方向不对。

把日志和配置对完,能解释这个现象的基本就这几处。nginx 复用了后端刚关闭的连接,请求发出去就收到 RST。还有一种是upstream 块里没配 keepalive 参数,连接池根本没启用。

少数情况下是keepalive_requests 太大,一条连接上跑了上万请求被后端主动断开。

第一件事是确认连接池参数是否存在

nginx -T | grep -n -A3 'upstream '

接着把后端空闲超时调长并固定连接数

printf 'upstream app {\n  server 10.0.0.21:8080;\n  keepalive 64;\n  keepalive_timeout 60s;\n}\n' > /etc/nginx/conf.d/upstream.conf

请求头里显式声明短连接,避免复用失效

sed -i 's#proxy_set_header Connection ""#proxy_set_header Connection ""#' /etc/nginx/conf.d/proxy.conf

reload 后统计 502 是否消失

nginx -s reload && awk '$9==502' /var/log/nginx/access.log | wc -l

别只看报错消失,验证要多做一步。连续观察一小时,access.log 里 502 的数量为 0,error.log 不再出现 upstream prematurely closed,后端连接数稳定在设定值附近。

keepalive 连接池要求 proxy_http_version 1.1 且 Connection 头置空,少一条就退化成短连接;两端的 idle 超时最好让 nginx 更短,由它主动关。如果同一现象隔几天又出现,说明根因没找到,别当偶发处理。

作者 9823189