站点 5xx 分层定位:500、502、503、504 在共享主机与 VPS 上分别该查哪一层

5xx 错误分层定位封面

站点突然返回 5xx,很多人的第一反应是重启服务器、换 PHP 版本,折腾半小时才发现问题出在一条写错的 .htaccess 规则上。这篇文章按状态码讲清楚如何定位:500、502、503、504 分别对应应用、网关、资源、超时四类故障,而共享主机(一台服务器划分多个站点、用户没有 root 权限)和 VPS(虚拟专用服务器,有独立系统和 root 权限)能拿到的排查入口差别很大。方向选错,日志看到天亮也没有结论。

为什么同一个 5xx 要拆成四层看

5xx 的含义很单纯:错误由服务端产生。但“服务端”不是一台机器,而是一条链:接入层是 Web 服务器(Nginx 或 Apache),中间是应用运行时(PHP-FPM、Node、Python 进程),再往下是数据库、缓存和外部接口。链上每一环都可能返回 5xx,只是状态码不同。

状态码本身就是断点的坐标。500 表示应用自己崩了,请求已经进到 PHP 里;502 表示网关连接后端失败,请求根本没送到应用;503 表示后端明确拒绝了这次请求,因为它没有余量;504 表示后端还在跑,但慢到网关放弃等待。四类故障的日志位置、可改参数、责任方都不一样。

真正的分水岭是权限。共享主机看不到 Nginx 配置,改不了 php.ini,也没有 root 读系统日志;VPS 全部可见,还能用 top、ss 往下钻。同一个 502,VPS 上三分钟能定位到 PHP-FPM 进程池打满,共享主机上只能先看面板错误日志、再排查插件和 .htaccess,其余交给工单。排查顺序必须跟着权限走,而不是跟着搜索引擎第一篇教程走。

5xx 状态码与责任层对应关系

500 Internal Server Error:先怀疑应用层

500 是应用抛出的错误,绝大多数对应 PHP 的 fatal error:调用了不存在的函数、内存超限、语法错误,或者用了与当前 PHP 版本不兼容的扩展。

在共享主机上,你能动的只有三个地方,查完基本覆盖八成 500:

  • 控制面板的错误日志:找到对应站点的 error_log,看最近一条 fatal error 的文件名和行号,这是最直接的证据
  • .htaccess 与 PHP 版本:面板里切换过 PHP 版本后,旧插件里的废弃函数会立刻报 500;.htaccess 多一行错误的 php_value 也会让整站 500
  • 文件权限:目录 755、文件 644,wp-config.php 被改成 777 反而会被部分主机直接拒绝执行

在 VPS 上可以继续往下钻,看该请求有没有进到 PHP,再看 PHP-FPM 的错误输出:

tail -n 50 /var/log/nginx/error.log
journalctl -u php8.3-fpm -n 50 --no-pager
php -l /var/www/site/index.php

php -l 只做语法检查,但能立刻排除改代码改崩的情况。要把访问日志与错误日志对起来看,可参考服务器访问日志分析,用报表代替手工 grep。

502 Bad Gateway:网关连不上后端

502 的语义很明确:Nginx(或负载均衡器)作为网关,把请求转给 upstream 时失败了。原因通常三种——后端没有监听那个端口、进程崩溃后 socket 消失、响应超时被上游断开。

在 VPS 上,先用两条命令确认后端到底有没有活人:

ss -lntp | grep 9000
curl -I --max-time 5 http://127.0.0.1:9000/status

如果 9000 端口没有进程监听,问题就结束了:去 systemctl status php8.3-fpm 看进程池为什么没起来。如果端口在监听但日志里反复出现 connect() failed (111: Connection refused),说明 socket 路径对不上,或 pool 的 listen 与 Nginx 的 fastcgi_pass 指向了两个位置。多台后端时,单节点被健康检查摘除也会造成间歇性 502,做法见Nginx 负载均衡排障。

共享主机上没有 upstream 给你调,502 通常对应两种现实:站点进程被资源限制杀掉,或并发打满后面的 PHP 池。你能做的是把单请求变轻——关掉长期占进程的插件、静态资源交给缓存、定时任务挪到低峰期。进程池参数的换算思路仍然适用,可参考PHP-FPM 进程池调优里 pm.max_children 与内存的关系,只是执行人变成了主机商。

网关与后端进程之间断开的位置

503 Service Unavailable:主动拒绝请求

503 和前两个不一样,它是“服务还在,但现在处理不了”。四个常见来源:PHP-FPM 的 pm.max_children 打满后新请求被丢弃;Apache 的 MaxRequestWorkers 用尽;WAF 或限流规则把突发流量判成攻击;站点处于维护模式(WordPress 的 .maintenance 文件生效时也返回 503)。

判断是不是容量问题,做一个乘法就够:pm.max_children 乘以单个 PHP 进程的常驻内存,必须小于可用内存。8 个进程、每个 60MB 就要 480MB 以上,再加 MySQL 和系统开销。把 max_children 调到 30 而不加内存,系统会用 swap,502 和 504 一起出现。

共享主机的 503 多来自平台侧并发上限或 CPU 秒数限制,面板“资源使用”页会有对应尖峰,日志里表现为同一时间点大量请求被拒。这时扩容比调参有效;先分清是流量涨了还是单请求太重,可对着服务器 CPU 负载过高排查里的 top 与 pidstat 方法看谁在吃资源。

504 Gateway Timeout:慢,而不是断

504 和 502 只差一个字,含义完全不同:后端还活着,只是慢到网关等不下去。Nginx 的 fastcgi_read_timeout 与 proxy_read_timeout 默认 60 秒,超过就返回 504,而 PHP 那边可能还在跑一个巨大的查询。

所以 504 的第一步不是调超时,而是找出谁慢。用一条命令测出后端真实耗时:

curl -o /dev/null -s -w "状态码:%{http_code} 总耗时:%{time_total}s\n" https://你的域名/

如果首页 1 秒内返回、只有某个页面 504,问题就在那个页面的业务逻辑里。接着看数据库:慢查询、锁等待、连接数耗尽都会让 PHP 卡住;连接数打满时 504 和 500 会交替出现,处理思路见数据库连接数超限排查。

在共享主机上你改不了超时阈值,能做的是把单请求耗时压下来:拆分长任务、把同步导入和推送改成队列、给动态页加缓存。这类优化对 502、503、504 同时有效,减的是同一份负载。

共享主机与 VPS 的可见范围差异

四类放进同一张判断表,最容易搞错的是“我能看到什么”。差别集中在四点:

  • 日志入口:共享主机只有面板里的站点错误日志,条数有限;VPS 有 /var/log/nginx/error.log、journalctl、php-fpm 慢日志三个独立通道
  • 配置权限:共享主机只能写 .htaccess 和有限的 user.ini;VPS 可以直接改 php.ini、nginx.conf、pool.d/*.conf
  • 进程可见性:共享主机看不到自己的进程树;VPS 能用 top、pidstat、iftop 实时观察
  • 处置手段:共享主机是提工单、换套餐、关插件;VPS 是自己调参、加内存、拆服务

这个差异直接决定排查顺序:没有 root 就从最上层往下查(日志→版本→插件→规则),有 root 就从最底层往上查(资源→进程→网关配置→代码)。反过来做,只会在没权限的地方反复确认一个改不动的配置。

一套五分钟能跑完的定位顺序

无论哪个平台,这五步当固定动作,多数 5xx 五分钟内就有方向:

  1. 记下状态码、出问题的 URL 和精确到分钟的时间点,后面所有日志都按这个时间窗切
  2. 打开对应层的日志,只看该时间点前后两分钟,别从头翻到尾
  3. 用最小请求复现:先 curl -I 首页,再单独请求一个只有健康检查的探针页
  4. 一次只改一处(版本、超时、进程数、规则),改完立即重启对应服务,避免两个变量混在一起
  5. 观察五分钟,确认错误率回落再收工,同时把这次的日志片段留档,下次同类故障能直接比对

排查顺序与对应日志入口

总结

5xx 不是“服务器坏了”的同义词,它是四类断点的坐标:500 看应用代码和 PHP 版本,502 看网关与后端的连接,503 看资源余量与限流,504 看单请求慢在哪一段。共享主机与 VPS 的差别不在故障本身,而在你能否读到那层的日志。

如果你正对着一片 5xx 页面,建议先按上面的顺序记下状态码、时间点和日志片段,再决定改配置还是提工单。站点长期反复出现 502 或 503,说明规格跟不上访问量,可以考虑 Hostease 的 VPS 主机,把进程池与超时的调整权拿回自己手里。

发表评论