《100个“反常识”经验15:Nginx 502排查:从应用到内核》
本期摘要502 Bad Gateway 是 Nginx 最让人头疼的错误码之一。它不像 404 那样明确文件不存在而是表示“上游服务器返回了无效响应”。本文从一次真实故障切入按“客户端 → Nginx → 应用 → 数据库”的链路分层排查涵盖 upstream 超时、连接数耗尽、缓冲区不足、PHP‑FPM 崩溃、内核 backlog 溢出等常见原因。读完你就能在收到 502 告警时快速定位是 Nginx 自身问题、后端应用问题还是系统层面问题。一次让人怀疑人生的故障某个促销日业务高峰大量用户反馈页面打不开。Nginx 日志里全是text[error] 12345#0: *987654 connect() failed (110: Connection timed out) while connecting to upstream502 扑面而来。运维同事第一反应“后端服务挂了”但检查应用进程一切正常检查数据库也无异常。重启 Nginx 后短暂恢复几分钟后又出现 502。折腾了两个小时发现问题出在 Nginx 与 PHP‑FPM 之间的 keepalive 配置不当加上 upstream 响应过慢导致连接池被耗尽。502 的本质Nginx 作为反向代理接收到客户端请求后需要向upstream后端应用服务器发起新的请求。如果 Nginx 无法得到有效的 HTTP 响应就会返回 502。常见的上游类型HTTP 后端Tomcat、Gunicorn、PHP‑FPM、Java 应用FastCGIPHP‑FPMuWSGIPython代理服务器本身排查四步法第一步查看 Nginx 错误日志bashtail -f /var/log/nginx/error.log错误日志会给出具体原因常见错误包括日志关键字含义排查方向connect() failed (110: Connection timed out)连接上游超时upstream 服务不可达或响应慢connect() failed (111: Connection refused)上游端口没开upstream 服务未启动或挂掉upstream timed out (110: Connection timed out)读取响应头超时upstream 处理太慢no live upstreams所有上游都挂了检查 upstream 健康状态client intended to send too large body请求体过大调大client_max_body_size第二步检查 upstream 服务状态如果是 HTTP 代理直接curl测试bashcurl -v http://127.0.0.1:8080/health # 假设 upstream 在 8080 端口如果超时或拒绝连接问题在后端应用。如果是 PHP‑FPMbashsystemctl status php7.4-fpm netstat -an | grep 9000 # 检查端口监听第三步检查 Nginx 与 upstream 之间的连接连接数是否耗尽bashss -an | grep 8080 | wc -l # 看连接数 netstat -an | grep 8080 | grep TIME_WAIT | wc -l如果 TIME_WAIT 堆积过多调整内核参数或 Nginx keepalive。upstream 响应时间在 Nginx 日志中记录请求时间bashlog_format timed $remote_addr - $request_time - $upstream_response_time - $request; access_log /var/log/nginx/access.log timed;$request_timeNginx 处理总时间$upstream_response_time上游服务器响应时间如果$upstream_response_time很大说明后端慢如果不大但$request_time大可能是 Nginx 发送响应给客户端慢网络问题。第四步系统层面检查net.core.somaxconn监听队列长度bashsysctl net.core.somaxconn # 默认 128高并发时容易溢出检查 Nginx backlog 配置bashlisten 80 backlog1024; # 增加队列容量文件句柄限制bashulimit -n # 查看当前进程可打开文件数 # 修改 /etc/security/limits.conf * soft nofile 65535 * hard nofile 65535常见场景及解决方案场景日志特征解决方案PHP‑FPM 响应慢upstream timed out, 但curl能通调大fastcgi_read_timeout优化 PHP 代码后端服务连接池满connect() failed (110: Connection timed out)增加后端服务连接池或调大 Nginxproxy_connect_timeoutTIME_WAIT 爆炸ss看到大量 TIME_WAIT开启proxy_http_version 1.1和proxy_set_header Connection 启用 keepalive请求体过大client intended to send too large body增加client_max_body_sizebacklog 溢出listen queue overflow系统日志增大net.core.somaxconn和 Nginxbacklog僵尸 upstream 被标记为 downno live upstreams检查健康检查配置必要时用max_fails0禁止标记为 down永久防范方案1. 合理设置超时参数nginxhttp { proxy_connect_timeout 5s; # 连接上游超时 proxy_send_timeout 10s; # 发送数据超时 proxy_read_timeout 10s; # 接收响应超时 fastcgi_read_timeout 60s; # FastCGI 专用 }2. 启用 upstream keepalivenginxupstream backend { server 127.0.0.1:8080; keepalive 32; # 保持空闲连接数 } server { location / { proxy_http_version 1.1; proxy_set_header Connection ; proxy_pass http://backend; } }3. 使用健康检查商业版 Nginx 支持主动健康检查。开源版可通过max_fails和fail_timeout控制nginxupstream backend { server 10.0.0.1:8080 max_fails3 fail_timeout30s; }4. 监控与告警监控 Nginx error.log 中 502 的数量监控 upstream_response_time 的 P99 值监控 Nginx 连接数、TIME_WAIT 数量下期预告《100个“反常识”经验16Docker容器退出日志里什么都没有》
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2567606.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!