线上遇到 404 时,我以前常常先怀疑程序路由,改了几处配置后才发现,真正的问题可能只是请求路径多了一个斜杠。后来我给自己定了一套固定流程:先看时间,再看访问日志,最后才动配置。
从一个时间点开始,而不是从猜测开始
浏览器报错时,先记下发生时间、访问路径和状态码。随后在 Nginx 或应用日志中定位同一时刻的请求:
tail -n 200 /var/log/nginx/access.log
tail -n 200 /var/log/nginx/error.log
journalctl -u nginx --since "10 minutes ago"访问日志告诉我“请求实际到达了哪里”,错误日志则更接近“服务器为什么拒绝它”。如果两边都没有记录,问题可能发生在更前面的 DNS、CDN 或安全组;如果 Nginx 有记录而应用没有,排查重点就应该放在反向代理和上游端口。
把 404 拆成几个小问题
我通常按下面的顺序排查:
- 请求的域名是否命中了正确的
server_name。 - Nginx 的
location是否匹配了预期路径。 proxy_pass拼接路径时有没有多一个或少一个斜杠。- 上游应用是否真的注册了这个路由。
- 静态文件是否存在,以及 Nginx 用户是否有读取权限。
每一步只验证一个假设,并记录结果。这样即使最后需要回滚,也能知道是哪一次改动带来了变化,而不是把所有配置一起改得面目全非。
修复后要重放原始请求
问题修好后,我会用原来的 URL 再请求一次,并补充一个不存在的路径作为负例:
curl -I https://example.com/原始路径
curl -I https://example.com/this-path-should-not-exist正常页面应该返回预期状态码,不存在的路径仍然应该是 404。只有正例和负例都符合预期,才能说明修复没有把错误处理一起破坏。
这次经历让我重新认识日志:它不是出问题之后才去翻的“黑匣子”,而是系统运行过程的时间线。只要给日志保留清晰的时间、请求路径和错误上下文,很多看似偶发的问题,都能被还原成一条可解释的因果链。