
访问网站时出现503 Service Unavailable,表示服务器当前无法处理请求,但这种状态通常是暂时性的。它可能来自Nginx、Apache、CDN、负载均衡器、PHP-FPM、Java应用、Node.js服务,也可能是网站进入维护模式后主动返回的结果。
503并不等于服务器一定宕机。服务器仍然可以联网、Nginx也可能正常运行,只是后端服务不可用、请求队列已满、进程池耗尽,或者限流规则拒绝了当前请求。
本文介绍如何判断503由哪一层返回,并使用curl、systemctl、journalctl、ss、Nginx日志和系统资源指标逐步定位故障。示例以常见Linux、Nginx和PHP-FPM环境为主,也适用于反向代理Java、Node.js、Python等应用的场景。
一、503状态码表示什么
HTTP 503表示服务暂时不可用。常见特点包括:
- 故障可能在短时间后恢复。
- 服务可能主动进入维护状态。
- 网关可以访问,但后端应用暂时不能处理请求。
- 服务器资源或应用并发达到上限。
- 限流、连接限制或过载保护主动拒绝请求。
部分503响应会携带Retry-After响应头,用于提示客户端稍后重试。但并不是所有503响应都会包含该字段。
503与其他常见状态码的区别:
| 状态码 | 常见含义 | 优先排查方向 |
|---|---|---|
| 500 | 应用内部处理出错 | 程序异常、依赖、代码和应用日志 |
| 502 | 网关收到无效的上游响应 | 上游进程、端口、协议和响应格式 |
| 503 | 服务暂时不可用或主动拒绝 | 维护、限流、队列、进程池和过载 |
| 504 | 网关等待上游响应超时 | 慢请求、数据库、网络和超时配置 |
实际系统可能通过自定义配置改变返回状态码,因此最终仍应结合响应头、页面内容和日志判断。
二、先确认503由哪一层返回
在客户端执行:
curl -I https://example.com/
查看完整请求过程:
curl -vk https://example.com/
重点关注:
Server响应头。- 是否存在CDN或代理相关响应头。
- 是否包含
Retry-After。 - 响应页面是CDN、Nginx、应用还是网站程序的模板。
- 所有页面都返回503,还是只有动态页面或特定接口异常。
分别测试公网域名和源站:
curl -I https://example.com/
curl -I http://127.0.0.1/ -H 'Host: example.com'
如果源站正常而公网域名返回503,重点检查CDN、负载均衡、WAF和回源配置。
如果源站本机也返回503,继续检查Nginx规则和后端应用。
如果只有某个接口返回503,问题更可能位于该接口对应的应用、依赖服务或局部限流规则。
三、保存故障现场再重启服务
遇到503时,不建议第一步就重启服务器。重启可能暂时恢复服务,却会清除进程、连接队列和部分日志现场,使真正原因无法定位。
先记录时间和基础状态:
date
uptime
free -h
df -h
df -i
vmstat 1 5
查看资源占用较高的进程:
ps -eo pid,ppid,user,%cpu,%mem,rss,stat,etime,comm,args \
--sort=-%cpu | head -n 20
再按内存排序:
ps -eo pid,ppid,user,%cpu,%mem,rss,stat,etime,comm,args \
--sort=-rss | head -n 20
需要重点确认:
- 系统负载是否突然升高。
- 可用内存是否接近耗尽。
- 是否持续发生Swap换入换出。
- 磁盘空间或inode是否已满。
- 应用进程是否消失、反复重启或占满CPU。
- 是否存在大量不可中断的
D状态进程。
四、检查Nginx和后端服务状态
查看Nginx:
sudo systemctl status nginx --no-pager
查看PHP-FPM。具体服务名取决于系统和PHP版本:
systemctl list-units --type=service | grep -E 'php.*fpm'
例如:
sudo systemctl status php8.3-fpm --no-pager
如果是其他应用:
sudo systemctl status myapp.service --no-pager
查看最近日志:
sudo journalctl -u nginx --since '30 minutes ago' --no-pager
sudo journalctl -u php8.3-fpm --since '30 minutes ago' --no-pager
sudo journalctl -u myapp.service --since '30 minutes ago' --no-pager
常见异常包括:
- 服务启动失败或退出。
- 配置文件语法错误。
- 端口被占用。
- 内存不足被系统终止。
- 应用依赖连接失败。
- 进程达到最大并发。
- systemd因连续失败限制重启。
五、检查Nginx错误日志和访问日志
常见日志位置:
sudo tail -n 200 /var/log/nginx/error.log
sudo tail -n 200 /var/log/nginx/access.log
实时观察:
sudo tail -f /var/log/nginx/error.log
筛选503:
sudo awk '$9 == 503 {print}' /var/log/nginx/access.log | tail -n 100
如果使用自定义日志格式,状态码所在字段可能不是第9列,更可靠的方法是根据实际log_format解析。
排查时关注:
- 503是否集中在某个URI。
- 是否集中在某些来源IP。
- 是否突然出现流量高峰。
- 503前后是否伴随502或504。
- 错误日志是否出现连接失败、共享内存不足或限流提示。
- 故障是否与发布、备份、定时任务或爬虫访问时间重合。
六、确认上游端口或Unix Socket是否可用
查看监听端口:
sudo ss -lntp
检查指定端口:
sudo ss -lntp | grep ':9000 '
测试HTTP上游:
curl -v http://127.0.0.1:8080/health
测试TCP端口:
nc -vz -w 3 127.0.0.1 8080
如果PHP-FPM使用Unix Socket:
sudo ls -l /run/php/
需要确认:
- Nginx配置的端口与应用实际监听端口一致。
- Socket文件确实存在。
- Nginx工作进程用户有权访问Socket。
- 应用没有只监听错误的地址。
- 容器端口和宿主机映射正确。
- 应用重启后Socket路径没有变化。
查看Nginx最终配置:
sudo nginx -T
只做语法检查:
sudo nginx -t
修改配置后应先执行nginx -t,确认成功再重新加载:
sudo systemctl reload nginx
七、Nginx限流可能主动返回503
Nginx的limit_req模块用于限制请求速率。请求超过限制并被拒绝时,默认状态码可以是503。
检查配置:
sudo nginx -T | grep -nE 'limit_req|limit_req_zone|limit_req_status'
示例:
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
server {
location /api/ {
limit_req zone=api_limit burst=20 nodelay;
}
}
如果用户正常访问也频繁触发503,需要判断:
- 限制维度是否合理。
- CDN或反向代理后是否把所有访客识别成同一个IP。
burst是否过小。- 接口是否存在前端重复请求。
- 爬虫或攻击流量是否集中。
- 日志中是否存在限流拒绝信息。
可以显式把限流状态码改为429,使“请求过多”与“服务不可用”更容易区分:
limit_req_status 429;
不要为了消除503直接删除全部限流。应先识别真实客户端IP,修正阈值,并确认应用能够承受放宽后的并发。
八、检查连接数限制和文件描述符
查看Nginx连接相关配置:
sudo nginx -T | grep -nE 'worker_connections|worker_rlimit_nofile|limit_conn'
查看进程限制:
pid=$(cat /run/nginx.pid)
cat /proc/$pid/limits
查看系统文件描述符:
cat /proc/sys/fs/file-nr
查看某个服务当前打开的文件:
sudo ls /proc/$(pgrep -o nginx)/fd | wc -l
当进程或系统达到文件描述符上限时,可能无法接受新连接、打开日志、连接Socket或读取文件。
不要只修改worker_connections。实际并发能力还受文件描述符、上游连接、内存、内核队列和应用处理能力影响。
九、PHP-FPM进程池耗尽
WordPress、PHP商城和其他PHP网站出现503时,PHP-FPM进程池耗尽是常见原因之一。
检查日志:
sudo journalctl -u php8.3-fpm --since '30 minutes ago' --no-pager
查看池配置:
grep -R -E '^(pm|pm\.max_children|pm\.start_servers|pm\.min_spare_servers|pm\.max_spare_servers|pm\.max_requests|request_slowlog_timeout|slowlog)' \
/etc/php/*/fpm/pool.d/
重点参数:
pm.max_children:允许同时处理请求的最大子进程数。pm.start_servers:动态模式启动时创建的进程数。pm.min_spare_servers:最少空闲进程数。pm.max_spare_servers:最多空闲进程数。pm.max_requests:子进程处理一定请求后重建,可用于缓解长期内存增长。
如果状态页已安全启用,可关注:
listen queue是否持续大于0。idle processes是否长期为0。active processes是否达到总进程数。max children reached是否持续增加。slow requests是否增长。
状态页可能暴露请求URL和资源信息,只能允许本机、内网监控或可信IP访问,不能直接公开到互联网。
不要盲目提高pm.max_children。可以先估算单个PHP-FPM进程的实际内存:
ps --no-headers -o rss -C php-fpm8.3 |
awk '{sum+=$1; n++} END {if(n) printf "avg=%.1f MB, processes=%d\n",sum/n/1024,n}'
进程数过高会消耗更多内存,严重时触发Swap或OOM,反而让503更加频繁。
十、检查CPU、内存和OOM
查看系统:
uptime
free -h
vmstat 1 10
检查OOM记录:
sudo journalctl -k --since '2 hours ago' |
grep -iE 'out of memory|oom|killed process'
如果应用被OOM Killer终止,重启应用只能暂时恢复。还应继续确认:
- 是否存在内存泄漏。
- 进程并发是否设置过高。
- 缓存或队列是否无限增长。
- 是否在同一时间执行备份、压缩或批处理。
- 容器内存限制是否过低。
- 系统是否缺少合理的资源余量。
查看容器状态:
docker ps -a
docker stats --no-stream
查看容器退出原因:
docker inspect container_name \
--format '{{.State.Status}} {{.State.ExitCode}} {{.State.OOMKilled}}'
十一、检查磁盘空间、inode和只读文件系统
应用无法写入会话、缓存、日志、临时文件或数据库时,也可能主动返回503。
检查磁盘:
df -h
df -i
检查文件系统是否只读:
findmnt -no TARGET,OPTIONS /
查看内核存储错误:
sudo journalctl -k --since '2 hours ago' |
grep -iE 'I/O error|read-only|filesystem|ext4|xfs'
重点检查:
/var、/tmp、网站目录和数据库目录。- inode是否耗尽。
- 日志是否快速增长。
- 文件系统是否因错误被重新挂载为只读。
- 容器可写层是否占满。
不要看到磁盘满就直接删除未知文件。应先使用du或日志工具定位来源,再按服务规则安全清理。
十二、检查数据库、Redis和外部依赖
应用本身运行正常,也可能因为数据库、Redis、消息队列或第三方接口不可用而返回503。
检查常见服务:
sudo systemctl status mysql --no-pager
sudo systemctl status redis-server --no-pager
测试数据库端口:
nc -vz -w 3 127.0.0.1 3306
测试Redis:
redis-cli PING
常见问题包括:
- 数据库连接数耗尽。
- SQL慢查询导致应用线程堆积。
- Redis内存达到上限。
- DNS解析异常导致外部依赖连接缓慢。
- 消息队列积压。
- 第三方接口超时,应用没有做好降级。
应结合应用日志确认503是应用主动返回,还是代理层生成。
十三、WordPress维护模式导致503
WordPress升级核心、主题或插件时,会在站点根目录创建.maintenance文件。升级中断后,该文件可能没有正常删除,使网站持续显示维护状态。
检查:
ls -la /path/to/wordpress/.maintenance
确认当前没有升级任务,并做好备份后再移除:
rm /path/to/wordpress/.maintenance
还应检查:
- 插件是否主动启用了维护模式。
- CDN是否缓存了维护页面。
- PHP错误是否发生在升级之后。
- 文件权限和依赖是否完整。
不要只删除维护文件就结束排查。如果升级过程失败,应继续确认插件、主题、数据库更新和文件完整性。
十四、CDN、WAF和负载均衡返回503
当源站本机正常,而用户通过域名访问503时,应检查前置网络服务。
常见原因:
- CDN无法连接源站。
- 源站IP或回源端口填写错误。
- 回源协议HTTP与HTTPS不一致。
- WAF规则误拦截。
- 负载均衡健康检查失败。
- 所有后端节点被标记为不可用。
- CDN边缘节点限流或服务异常。
- 源站只允许旧的CDN出口IP。
使用curl分别测试:
curl -I https://example.com/
curl -I http://SOURCE_IP/ -H 'Host: example.com'
如果HTTPS源站要求SNI:
curl -vk --resolve example.com:443:SOURCE_IP https://example.com/
这能让请求直接连接指定源站IP,同时保留正确的域名和TLS SNI。
十五、如何安全恢复服务
已经确认故障来源后,可以按以下原则恢复:
服务停止
先查看日志和配置,再启动或重启:
sudo nginx -t
sudo systemctl restart nginx
sudo systemctl restart php8.3-fpm
应用过载
- 临时限制异常流量。
- 暂停高消耗定时任务。
- 对非核心接口降级。
- 增加健康节点。
- 修复慢查询和阻塞请求。
- 在确认内存余量后调整进程池。
磁盘或内存耗尽
- 先停止异常增长来源。
- 安全清理明确可删除的数据。
- 恢复必要的磁盘和内存余量。
- 再启动受影响服务。
配置错误
- 使用配置检查命令验证。
- 回滚到已知可用版本。
- 重新加载后观察日志。
- 从本机和公网分别验证。
恢复后执行:
curl -sS -o /dev/null -w '%{http_code} %{time_total}\n' https://example.com/
并持续观察:
sudo journalctl -u nginx -f
十六、不要用这些方式“解决”503
以下操作可能暂时隐藏问题,但通常会增加后续风险:
- 不看日志直接重启整台服务器。
- 无限提高PHP-FPM进程数。
- 删除全部Nginx限流规则。
- 把所有防火墙和安全组规则关闭。
- 只增加代理超时时间。
- 看到磁盘满就批量删除未知目录。
- 将状态页直接开放到公网。
- 在流量高峰直接执行高风险配置变更。
503的根因通常是“服务能力暂时低于请求压力”或“某个必要组件不可用”。真正的修复需要找到具体瓶颈,而不是只让错误页面短暂消失。
十七、建议建立哪些监控
建议持续记录:
- HTTP 503数量和比例。
- 按域名、URI、节点和上游拆分的状态码。
- Nginx活跃连接和请求速率。
- 上游响应时间和失败次数。
- PHP-FPM活动进程、空闲进程、等待队列和最大子进程触发次数。
- 应用线程池、连接池和队列长度。
- CPU、系统负载、内存、Swap和OOM事件。
- 磁盘空间、inode和I/O延迟。
- 数据库连接数、慢查询和锁等待。
- Redis内存、淘汰数量和连接数。
- CDN回源状态及负载均衡健康节点数量。
告警不能只看“网站是否能打开”。即使整体可用,某个接口持续503、等待队列增长或空闲进程降为0,也应提前处理。
十八、推荐的完整排查顺序
网站出现503时,可以按下面的顺序操作:
- 使用
curl -I查看状态码、响应头和返回层级。 - 对比公网域名、源站IP和本机访问结果。
- 保存故障时间、系统负载、内存、磁盘和进程现场。
- 检查Nginx、PHP-FPM或应用服务状态。
- 查看Nginx错误日志、访问日志和应用日志。
- 使用
ss、curl或nc检查上游端口和Socket。 - 使用
nginx -T检查限流、连接限制和代理配置。 - 确认是否由
limit_req主动返回503。 - 检查PHP-FPM等待队列和
max children reached。 - 检查CPU、内存、OOM、磁盘和inode。
- 检查数据库、Redis和外部依赖。
- 检查WordPress维护模式或应用维护开关。
- 如果源站正常,检查CDN、WAF和负载均衡。
- 修复根因后再有针对性地重启或重新加载服务。
- 从内外网络验证恢复,并持续观察日志和监控。
总结
503 Service Unavailable表示当前服务暂时不能处理请求,但返回503的组件可能是CDN、Nginx、限流模块、PHP-FPM、应用程序或维护模式。
排查的核心不是立即重启,而是先确认503由哪一层生成。使用curl对比公网、源站和本机响应,使用systemctl和journalctl检查服务,使用ss确认上游监听,再结合Nginx日志、PHP-FPM状态和系统资源定位具体瓶颈。
如果503来自流量高峰,应同时处理异常请求、应用并发、数据库性能和资源容量;如果来自维护或配置错误,应通过配置检查和安全回滚恢复。建立分层状态码、上游延迟、进程池队列和系统资源监控,才能在用户大面积看到503之前发现问题。




