话题:#IT疑难杂症诊疗室
摘要:一次“看似网络”的 502,排查链路绕了 3 小时,最终定位到 systemd 默认 LimitNOFILE 软限制。记录全过程,帮你下次 5 分钟解决。
现象
- 浏览器间歇 502 Bad Gateway
- Nginx error_log 大量
upstream prematurely closed connection - 后端健康接口 200,CPU/内存 均 < 30%
排查路线 & 命令
1. Nginx 端
tail -n 500 /var/log/nginx/error.log | grep 502
2. 后端
ab -n 10000 -c 100 http://127.0.0.1:8080/health
复现失败率 0.3%,无异常日志。
3. 系统资源
ss -s
TCP established 峰值 1021,接近 1024 理论上限。
4. systemd 软限制
systemctl show your-app.service -p LimitNOFILE
输出 LimitNOFILE=1024,而 Nginx worker 已占 600+。
根因
systemd 默认 DefaultLimitNOFILE=1024,SpringBoot jar 以 systemd 方式启动,句柄数满 → 新连接拒收 → Nginx 502。
解决
在 /etc/systemd/system/your-app.service 追加:
[Service]
LimitNOFILE=65536
重载并重启:
systemctl daemon-reload
systemctl restart your-app
502 立即消失,压测 2w 并发 0 失败。
复盘
- 502 不一定是「网络」或「代码」问题,先查 fd/端口 资源。
- systemd 托管的服务,limits 需显式声明,不受 /etc/security/limits.conf 控制。
- 给现场留一条 ulimit -n 检查命令,下次 5 分钟定位。
- 你在工作中还遇到过哪些“看似网络,实则系统”的诡异故障?欢迎留言交流,一起攒一本「IT 踩坑小册」!
扩展:通用 502 排查鱼骨图(收藏级)
| 层级 | 检查项 | 一句话命令 |
|---|---|---|
| 网络 | 端口是否 Listen | `ss -lntp |
| grep :80` | ||
| 网络 | 连接是否满 | ss -s |
| 系统 | fd 是否耗尽 | `lsof |
| wc -l` | ||
| 系统 | 本地端口范围 | cat /proc/sys/***/ipv4/ip_local_port_range |
| 系统 | 内核参数 |
ulimit -n / systemctl show xxx.service -p LimitNOFILE
|
| 应用 | 健康接口 | curl -w "%{http_code}\n" http://127.0.0.1:8080/health |
| 应用 | 线程死锁 | `jstack |
| grep -i deadlock` | ||
| 网关 | Nginx 超时 | `grep upstream /var/log/nginx/error.log |
| tail` |
懒人一键脚本
#!/bin/bash
echo ====== System FD ======
lsof |
wc -l
echo ====== Service Limit ======
systemctl show $1 -p LimitNOFILE
echo ====== Established ======
ss -s |
grep estab
echo ====== Port Usage ======
ss -lntp |
grep $2
./check_502.sh your-app 8080
可视化监控:10 行 Prometheus 规则
如果公司用 Prometheus,加两条 Alert 就能提前 5 分钟发现同类故障:
- alert: ServiceFD90Percent
expr: process_open_fds / process_max_fds > 0.9
for: 2m
annotations:
summary: "{{ $labels.job }} fd > 90%"
- alert: Nginx502Spike
expr: rate(nginx_http_responses_total{status="502"}[5m]) > 0.1
for: 1m
annotations:
summary: "502 spike {{ $value | humanize }}/s"
结果对比(数据说话)
| 指标 | 调优前 | 调优后 |
|---|---|---|
| 502 出现频率 | 0.3% | 0% |
| 最大并发 | 4k | 2.5w |
| 句柄占用 | 1021/1024 | 1.2w/65536 |
| 压测失败数 | 120/10w | 0/10w |
小结(金句收藏)
- 502 不是“网络玄学”,先画鱼骨图再动手,5 分钟定位不是梦。
- systemd 时代,limits 要显式声明,别再只改 /etc/security/limits.conf。
- 监控 > 排查 > 复盘,把故障变成文档,下次就是 1 分钟解决。