网站出现大量5xx状态码怎么办?服务器日志与搜索引擎抓取排查

网站在监控里突然出现一片红色的 5xx,是运维最不想看到的画面之一。5xx 代表服务器端出错:502 Bad Gateway、503 Service Unavailable、504 Gateway Timeout、500 Internal Server Error 都属于这一类。它和 4xx 有本质区别——4xx 多是客户端请求有问题(比如访问了不存在的地址),而 5xx 说明"服务器自己没扛住",是必须马上处理的事故。

更麻烦的是,5xx 会影响搜索引擎抓取。爬虫访问时拿到 5xx,会认为站点暂时不可用,短期内会降低抓取频率,长期大面积 5xx 会导致收录下降甚至降权。这篇文章给出从日志定位原因、到判断对收录影响、再到告警回滚健康检查的完整处置流程,目标是让你遇到 5xx 时能快速止血,而不是盯着错误页发呆。

一、先分清 5xx 的几种常见含义

不同 5xx 对应的方向不一样,先看状态码再动手,能省很多时间。

状态码 含义 典型根因
500 Internal Server Error 应用内部错误 代码异常、配置错误、文件权限
502 Bad Gateway 网关从上游收到无效响应 后端进程崩溃/未启动、端口不通
503 Service Unavailable 服务暂时不可用 过载、主动维护、后端全挂
504 Gateway Timeout 网关等待上游超时 后端处理太慢、依赖卡死、数据库慢
507 Insufficient Storage 存储不足 磁盘写满、配额耗尽

一个简单的判断口诀:502 多半是"后端没了",504 多半是"后端在但太慢",500 多半是"代码或配置报错",503 是"主动或被动拒绝了"。Nginx 作为反向代理时,这些错误经常是它转述后端(PHP-FPM、Java、Node 等)的状态。

二、从 Nginx 日志定位出错环节

排查第一站是 Nginx 的错误日志和访问日志。错误日志告诉你"发生了什么",访问日志告诉你"影响了哪些请求"。

# Nginx 默认错误日志位置,取决于发行版和编译参数
# Debian/Ubuntu: /var/log/nginx/error.log
# RHEL/CentOS/Rocky: /var/log/nginx/error.log(也可能在 /var/log/nginx/ 下)
ls -l /var/log/nginx/

# 实时看错误日志
sudo tail -f /var/log/nginx/error.log

# 统计错误日志里各类错误的出现次数(找出最高频的)
sudo awk '{print $0}' /var/log/nginx/error.log | grep -oE '\[(error|crit|alert|emerg)\]' | sort | uniq -c

# 统计访问日志里 5xx 的请求路径,找出是哪几个接口在崩
sudo awk '$9 ~ /^5/ {print $9, $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20

错误日志里最值得关注的关键词:

  • connect() failed (111: Connection refused) while connecting to upstream:Nginx 连不上后端,通常是后端进程没起或端口不对,对应 502。
  • upstream timed out (110: Connection timed out):后端太慢,超过 proxy_read_timeout,对应 504。
  • no live upstreams:所有后端都被标记为不可用,对应 502/503。
  • worker_connections are not enough:并发连接不够,Nginx 自身成了瓶颈。
  • upstream sent too big header:后端返回的响应头太大,超过缓冲区。

对应的上游配置参数也一并给出,方便你对照调整:

location / {
    proxy_pass http://backend;
    proxy_connect_timeout 5s;    # 连接后端超时
    proxy_send_timeout    60s;   # 发送请求给后端超时
    proxy_read_timeout    60s;   # 读取后端响应超时,504 常与此有关
    proxy_next_upstream error timeout http_502 http_503 http_504;
    proxy_buffer_size   16k;
    proxy_buffers       8 16k;
    proxy_busy_buffers_size 32k;
}

注意 proxy_read_timeout 调大只是"等更久",不解决后端本身慢的问题,属于临时缓解,根因还得回到后端。

三、排查后端应用日志与进程状态

Nginx 说"连不上后端",下一步就是看后端本身。不同技术栈日志位置不同:

# 进程是否活着
sudo systemctl status php-fpm      # 或 php8.1-fpm 等具体版本
sudo systemctl status nginx
ps aux | grep -E 'php-fpm|java|node|gunicorn' | grep -v grep

# PHP-FPM 日志(配置在 /etc/php-fpm.d/www.conf 或 /etc/php/*/fpm/pool.d/www.conf)
sudo tail -100 /var/log/php-fpm/www-error.log

# FPM 慢日志,定位慢请求
# 在 www.conf 里:request_slowlog_timeout = 5s ; slowlog = /var/log/php-fpm/www-slow.log
sudo tail -100 /var/log/php-fpm/www-slow.log

后端常见崩溃原因:进程被 OOM 杀掉(看 dmesg | grep -i oom)、代码有未捕获异常、依赖服务(数据库/Redis)连不上、部署时改了配置但没重启。dmesg 和 journalctl 能提供内核级线索:

# 看是否被 OOM 杀过
sudo dmesg -T | grep -i -E 'oom|killed process'
# RHEL/CentOS/Rocky 与 Debian/Ubuntu 都支持 systemd 的 journalctl
sudo journalctl -u php-fpm --since "1 hour ago" | tail -50

四、资源耗尽类 5xx 的排查

有一大类 5xx 不是代码问题,而是资源被打满:磁盘、内存、文件描述符、连接数。这类问题会表现为"平时好好的,流量一上来就崩"。

# 磁盘是否写满(写满会导致日志写不进、临时文件建不了、会话失败)
df -hT

# 内存与 swap
free -h
# 查看占用内存最高的进程
ps aux --sort=-%mem | head -10

# inode 是否耗尽(磁盘还有空间但 inode 满了也会报错)
df -i

# 打开的文件描述符总数与上限
cat /proc/sys/fs/file-nr
ulimit -n

# 网络连接数与各状态统计
ss -s
ss -ant | awk '{print $1}' | sort | uniq -c

如果 df -i 显示 inode 用满,常见原因是某目录里堆了海量小文件(比如未轮转的日志、大量临时会话文件)。如果连接数逼近上限,要看是正常流量还是被压测、被恶意刷。调整内核和进程限制属于系统级改动,务必先记录原值便于回滚,例如临时提高文件描述符上限:

# 临时生效(重启失效),仅用于应急验证
sudo sysctl -w fs.file-max=2097152
# 永久修改请写入 /etc/sysctl.d/99-tunning.conf 并 sysctl -p 使其生效

五、5xx 对搜索引擎抓取和收录的影响

这一点很多人忽略。搜索引擎爬虫遇到 5xx 的处理逻辑大致是:把 5xx 当作"服务器临时故障",短期不会立刻删掉已收录页面,但会降低抓取频率、推迟重抓。如果站点持续大面积 5xx,会出现几种后果:

  • 抓取预算被浪费,正常页面得不到及时抓取和更新。
  • 已收录页面可能因长期无法访问而在搜索结果中降权或消失。
  • 新页面迟迟不被收录。
  • 极端情况下整站被判定为不可靠,影响排名。

判断影响范围,可以分析爬虫访问的 5xx 比例:

# 统计各大搜索引擎爬虫拿到 5xx 的次数(示例 UA 关键词)
sudo awk -F'"' '/Googlebot|bingbot|Baiduspider/ && $0 ~ / [5][0-9][0-9] /' \
  /var/log/nginx/access.log | wc -l

# 更精确:按 UA + 状态码分组统计
sudo awk -F'"' '{ua=$6; split($2,a," "); code=a[2]; if(code ~ /^5/) print ua, code}' \
  /var/log/nginx/access.log | sort | uniq -c | sort -rn | head

如果爬虫请求里 5xx 比例很高,而普通用户请求正常,可能是爬虫触发了某个耗时接口或限流(这时也涉及第 067 篇的蜘蛛话题)。修复后到搜索引擎站长平台提交"抓取异常"或"重新抓取"申请,能加速恢复。

六、应对与止血:告警、回滚、健康检查、降级

出问题时的优先级是"先止血,再定位根因"。

第一步是告警要到位。用监控对 5xx 比例设阈值,比如"1 分钟内 5xx 占比超过 1%"或"错误数超过 100"就发通知。只盯服务器存活是不够的,必须监控业务指标。

第二步是能回滚就回滚。大量 5xx 若发生在一次部署之后,最快的止血方式是回退到上一个可用版本。

# 示例:用软链接发布的目录,回滚只需把 current 指回旧版本
ls -l /opt/app/releases/
# 把 current 指回上一个正常版本(注意确认旧版本代码存在且配置兼容)
sudo ln -sfn /opt/app/releases/2026-10-10_1200 /opt/app/current
sudo systemctl reload php-fpm    # 或 restart,视具体栈而定

回滚前务必确认目标版本确实可用,并留意数据库结构变更是否兼容,避免"代码回滚了、表结构没回滚"导致更糟。

第三步是健康检查。给后端配一个轻量健康接口,Nginx 或负载均衡据此剔除坏实例,避免把请求发给已挂的节点。

# 简单做法:用 Nginx 的 upstream 与被动健康检查
upstream backend {
    server 127.0.0.1:9000 max_fails=3 fail_timeout=30s;
    server 127.0.0.1:9001 max_fails=3 fail_timeout=30s;
    keepalive 32;
}
# 配合 proxy_next_upstream,请求失败时自动切到下一个后端

第四步是降级与限流。后端扛不住时,主动把非核心功能关掉(推荐位、评论、搜索联想),保住核心页面;同时用限流保护后端(详见第 066 篇)。降级是"牺牲部分功能换取整体可用",属于应急手段,流量恢复后要记得改回来。

七、一套可复用的排查顺序

把上面的内容整理成清单,遇到 5xx 按顺序走:

步骤 看什么 命令/位置
1. 确认范围 哪些 5xx、哪些 URL、多少量 access.log 按状态码统计
2. 看 Nginx 错误 是连不上还是超时 error.log
3. 看后端进程 是否存活、是否被 OOM systemctl status、dmesg
4. 看后端日志 应用层报错 php-fpm / 应用日志
5. 查资源 磁盘、内存、连接、inode df -h、free -h、ss -s
6. 查依赖 数据库、Redis 是否可用 连接测试、各自日志
7. 判断是否部署引起 是否刚发版 部署记录、回滚
8. 评估对爬虫影响 爬虫 5xx 比例 access.log UA 统计

常见问题

Q:502 和 504 怎么快速区分处理方向?
502 是后端"没了或没响应",先查后端进程是否存活、端口是否监听;504 是后端"在但太慢",先查后端处理耗时和依赖服务。方向不同,别混着查。

Q:重启一下就好了,需要深究吗?
需要。反复"重启就好"说明有隐藏的资源泄漏或配置问题,迟早会在你最不希望的时候爆发。记录每次发生的规律(时间、流量、操作),从中找共性。

Q:5xx 会不会让网站被搜索引擎惩罚?
短期少量不会,持续大面积会降低抓取和收录,严重时影响排名。修复后到站长平台提交重新抓取,能加快恢复。

Q:怎么区分是正常流量过大还是被攻击?
看请求特征:被攻击往往集中在少数 IP、特征 UA、固定 URL,且频率异常。用 access.log 按 IP 和 UA 统计即可看出。这时需要限流或封禁(注意别误封爬虫,见第 067 篇)。

Q:改了 proxy_read_timeout 从 60s 到 300s,好还是不好?
不一定好。它让 Nginx 更耐心地等慢后端,减少了 504 数量,但会占用连接和 worker 资源更久,可能把问题从"报错"变成"整体变慢"。应先查后端为什么慢。

总结

5xx 是"服务器自己的错",502 多为后端掉了、504 多为后端慢、500 多为代码或配置问题、503 是主动或被动拒绝。

排查沿"Nginx error.log → 后端进程 → 后端日志 → 资源(磁盘/内存/连接/inode)→ 依赖服务 → 是否刚部署"这条线走,多数问题能定位。

持续 5xx 会降低搜索引擎抓取频率、影响收录和排名,修复后要到站长平台提交重新抓取。

应急优先级是"先止血再定位":告警到位、能回滚就回滚、用健康检查剔除坏节点、必要时降级非核心功能并限流。

大的内核或超时参数调整要先记录原值,回滚前确认数据库结构兼容,"重启就好"的问题一定要追求根因。