top 截图是我最不愿意先看的东西之一。
CPU 3%,内存还剩一半,Load 0.18。这三项只能说明整机资源看上去没打满。502 从哪儿来的,还是不知道。
假设这次 502 出现在 order-api 发布之后,systemctl 仍显示 active (running)。这时候就别再补一张 df -h 了,先找 502 到底是谁返回的。
如果新版本可以安全回滚,先保留一次请求结果、故障实例和相关日志,再按预案回滚。用户还在报错时,恢复服务比现场完成根因分析重要。Google 的 SRE 故障排查章节 也把止损放在深挖根因之前。
留下的那次请求是这样测的:
bash
curl -sS -o /dev/null \
-w 'code=%{http_code} dns=%{time_namelookup} connect=%{time_connect} tls=%{time_appconnect} first=%{time_starttransfer} total=%{time_total}\n' \
https://shop.example.com/health
假设留下的记录是:
text
code=502 dns=0.006 connect=0.013 tls=0.041 first=0.058 total=0.058
DNS、TCP 连接和 TLS 握手都很快,502 也几乎立刻返回。这次请求已经到达能返回 502 的网关,客户端、解析和握手链路暂时往后排。接下来查网关为什么没从上游拿到正常响应。502 本身还不能证明应用进程已经退出,这一点在 RFC 9110 里写得很清楚。curl 各时间字段的含义可查官方手册。
代理日志里接着出现:
text
connect() failed (111: Connection refused) while connecting to upstream
upstream: "http://127.0.0.1:8080/health"
这行把问题又缩小了一截:Nginx 收到了请求,但它连接本机 8080 端口时被拒绝。此时再看监听套接字:
bash
ss -lntp 'sport = :8080'
没有输出。systemd 确实还看得到主进程,但它没有监听 Nginx 要找的 8080 端口。
再读这一轮发布后的服务日志:
bash
journalctl -u order-api --since '10:00'
里面有一句 server listening on 127.0.0.1:8081。对一下新旧配置,原因便落地了:应用端口从 8080 改成了 8081,反向代理配置没有一起改。前面每一步都只回答一个问题,没有哪一步靠"运维经验"猜答案。
我说的基础差不多就在这儿:知道一个请求为什么会经过 DNS、TCP、TLS 和 HTTP,知道端口后面是套接字和进程,也知道 systemd 与日志各能证明什么。最后还得从版本差异里找到那次端口修改,并把配置安全地退回去。