502 Bad Gateway因Keepalive配置错误时,本质是Nginx与上游连接复用失败,导致“连得上但聊不下去”;需查error.log中upstream prematurely closed connection等线索,验证上游Keepalive支持、Nginx配置对齐(proxy_http_version 1.1、Connection头清除)及系统资源限制。

502 Bad Gateway 出现时,如果和长连接(Keepalive)配置错误有关,本质是 Nginx 与上游服务之间连接复用失败,导致请求中途断开、响应不完整或连接被重置。这不是服务宕机,而是“连得上但聊不下去”。排查重点不在重启,而在确认连接是否真正复用、上游是否支持、Nginx 是否主动关掉空闲连接。
看 error.log 里有没有 keepalive 相关线索
Nginx 错误日志是第一手证据。打开 /var/log/nginx/error.log,搜索这些关键词:
- upstream prematurely closed connection:上游提前关闭连接,常见于上游未开启 Keepalive 或连接池耗尽
- recv() failed (104: Connection reset by peer):上游突然断连,大概率是后端服务主动踢掉了空闲连接
- no live upstreams:所有 upstream 节点都被标记为不可用,往往因连续失败触发健康检查下线,而根源常是 Keepalive 不匹配
验证上游是否真的支持并开启了 Keepalive
Nginx 的 keepalive 是单向的——它只管自己要不要复用连接,但能否复用,取决于上游是否也愿意保持连接。不能只看 Nginx 配了 keepalive 就认为万事大吉。
Linux 安全审计工具,检查 SSH 配置、开放/监听端口、防火墙规则(ufw/iptables/nftables)、失败登录尝试、sudoers 权限...
- 对 PHP-FPM:检查 pm.max_children 和 pm.max_requests。若后者设得太小(如 500),每个 worker 处理完固定请求数就会退出,连接自然中断;建议调高至 2000–5000 或设为 0(不限制)
- 对 Java/Tomcat:确认 server.xml 中 Connector 的 keepAliveTimeout 和 maxKeepAliveRequests 是否启用且足够长(例如 keepAliveTimeout="60000")
- 对 Node.js/Express:需显式设置 server.keepAliveTimeout = 60000 和 server.headersTimeout = 65000,否则默认 5 秒就断连
- 用 curl 直连上游测试:执行 curl -v http://127.0.0.1:8080/health,观察响应头是否有 Connection: keep-alive,且多次请求复用同一 TCP 连接(看复用的 socket 号是否一致)
检查 Nginx 的 upstream keepalive 配置是否合理
Keepalive 参数必须和上游能力对齐,否则形同虚设。常见错误是只加了 keepalive 32,却忘了配套的 HTTP 版本和 header 设置。
- upstream 块中必须包含:
upstream backend {
server 127.0.0.1:8080;
keepalive 32;
} - 对应 location 中必须启用 HTTP/1.1 并清除 Connection header:
location / {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
} - keepalive 数值不宜过大:32 是较稳妥值;超过 64 容易触发上游连接池溢出,反而增加 502 概率
排除内核与连接池资源瓶颈
即使配置正确,系统级限制也会让 Keepalive 失效。尤其在高并发下,大量空闲连接堆积会耗尽资源。
- 检查当前 ESTABLISHED 连接数:
ss -ant | grep ':8080' | grep ESTAB | wc -l,若接近或超过 net.core.somaxconn(默认 128),说明连接队列已满 - 确认 ulimit 和 worker 连接数匹配:
worker_connections 应 ≥ 上游 keepalive × upstream server 数 × 并发量预估;否则 Nginx 自身连接池先撑爆 - 临时加固(验证用):
echo 'net.ipv4.tcp_fin_timeout = 30' >> /etc/sysctl.conf
sysctl -p
避免 TIME_WAIT 连接长期占用端口,影响新连接建立

















