网站突然502了,老板在群里@你,怎么办?
咖啡刚喝一口,手机就震得像要跳桌。
群消息99+,监控红得刺眼,首页赫然挂着“502 Bad Gateway”——不是幻觉,是真的挂了。
别点刷新,先深呼吸。502不是服务器炸了,是中间人卡住了。按下面这几步走,10分钟内大概率能拉回来。
502错误到底是什么?先看懂再动手
502 是 HTTP 状态码,意思是“网关收不到后端的回音”。
它不等于你的网站代码崩了,也不等于数据库死了。而是 Nginx、CDN 或负载均衡器这类“传话员”,去敲你后端服务(比如 PHP-FPM、Java 应用)的门,结果没人应、门不开、或者等半天才慢吞吞递出一张废纸。
常见“传话员”:Nginx(最常见)、Apache 反向代理模式、Cloudflare、阿里云 SLB。
一个真实案例:客户一见502就狂重启 PHP,反复三次没用。最后翻 Nginx 错误日志,发现 proxy_pass http://192.168.1.100:8080 —— 后端 IP 写错了,压根连不到“餐厅”。改对地址,秒恢复。
第一步:5分钟内必须做的紧急检查清单
别开浏览器刷页面,直接上终端。打开两个 SSH 窗口,一个盯日志,一个跑命令。
后端服务还在跑吗?
systemctl status php-fpm(PHP 站)systemctl status tomcat(Java 站)ps aux | grep gunicorn(Python 站)
看一眼状态是不是 active (running),如果不是,先systemctl start xxx。立刻看 Nginx 错误日志
tail -f /var/log/nginx/error.log
别滑屏,盯着最新几行。关键词:“connect() failed”、“upstream timed out”、“no live upstreams”——这些就是破案线索。服务器是不是被榨干了?
top或htop快速扫一眼:CPU 长期 95%+?内存只剩几百 MB?MySQL 连接数飙到 max_connections?资源见底,请求自然排队超时。
关键动作:一边 tail -f error.log,一边敲 systemctl status php-fpm。日志里报哪一行错,你就去查对应的服务或配置。
第二步:根据错误日志,精准打击问题根源
日志不是天书,这几类报错,对应几类解法:
看到 “Connection refused to upstream”
→ 网关根本连不上后端。
可能:PHP-FPM 崩了、端口监听错了(比如配置写 8080,实际只开了 9000)、防火墙临时拦了内网通信。
马上做:systemctl restart php-fpm;检查 listen = 127.0.0.1:9000 和 Nginx 里的 proxy_pass 是否一致;iptables -L 看有无新规则。
看到 “upstream timed out”
→ 网关连上了,但后端卡住不给回应。
可能:某个 PHP 脚本死循环、数据库查询堵死、调第三方 API 一直 hang 住。
马上做:pstack $(pgrep php-fpm) 看进程在卡哪行;临时注释掉最近上线的功能模块;重启 PHP-FPM 清理积压。
一个具体场景:日志满屏“upstream timed out”,查进程发现一堆 PHP 在等地图 API 返回。把那段调用临时注释掉,reload Nginx,流量立刻回流。
第三招:这些配置陷阱,你可能一直没注意
平时风平浪静,一到大促或爬虫扫过来,就原形毕露。
PHP-FPM 子进程不够用pm.max_children 设太小(比如默认 5),10 个用户同时访问,第 6 个就得排队。排太久,Nginx 就甩出 502。
改法:按服务器内存算,每个 PHP 进程约占 30–80MB,留一半内存给系统,剩下除一下,填进 pm.max_children。
Nginx 超时时间太短proxy_read_timeout 60; 是默认值。但生成一份订单报表要 90 秒?Nginx 等不及,直接断连返 502。
改法:在对应 location 块里加 proxy_read_timeout 120;,别全局改,只针对耗时接口。
缓冲区小到装不下响应头
后端返回的 Set-Cookie 太长,或响应体带大 Base64 图片,超出 proxy_buffer_size 4k,也会触发 502。
改法:proxy_buffer_size 16k; proxy_buffers 8 16k;
第四招:当数据库成为“拖后腿”的元凶
502 报警响了,别光盯着 PHP。后端服务卡住,八成是被数据库拖死的。
快速诊断(MySQL):mysql -u root -p → SHOW PROCESSLIST;
重点找 State 是 Sending data、Locked、Copying to tmp table 且 Time 超过 30 秒的行。记下 Id,直接 KILL 12345; 干掉它。
后续必须做:
- 开启慢查询日志:
slow_query_log = ON,long_query_time = 2 - 对搜索字段加索引,尤其避免
LIKE '%关键词%'全表扫描 - 电商站曾因商品搜索没索引,在 50 万数据上全表扫,导致 PHP 进程集体卡死,502 频发。加完索引,问题消失。
第五招:预防大于治疗,如何让502不再复发
救火一次是本事,不着火才是真功夫。
- 服务自动复活:用
systemd的Restart=always,或 Supervisor 监控 PHP-FPM,崩了自动拉起。 - 资源提前预警:在你常用的监控面板(比如 Zabbix、Prometheus + Grafana、甚至宝塔后台)里,给 CPU、内存、MySQL 连接数设报警线,超 80% 就微信/钉钉告警。
- 上线前压一压:用
ab -n 1000 -c 100 https://yoursite.com/模拟并发,看 PHP-FPM 进程数和响应时间是否稳定。 - 外部依赖要兜底:调微信登录、短信接口,加
try/catch+ 默认返回,别让它卡住整个下单流程。
今天下班前就能做的“502防火墙”行动
别等下次报警。现在就打开终端,花 5 分钟加固:
- 执行
sudo nano /etc/php/{版本号}/fpm/pool.d/www.conf(Ubuntu/Debian)或/usr/local/php/etc/php-fpm.d/www.conf(编译安装) - 找到
pm.max_children,改成你算出来的安全值(例如:4G 内存服务器,设为20) - 找到
request_terminate_timeout,设为300(单位秒),确保它 > Nginx 的proxy_read_timeout - 保存后执行
sudo systemctl reload php-fpm - 登进你天天看的监控后台(宝塔、Zabbix、云厂商控制台),给“PHP-FPM 当前活跃进程数”和“服务器内存使用率”加上报警规则,阈值设 85%
做完这五步,下次 502 来敲门,你至少能笑着回一句:“稍等,我刚加固过。”