Nginx间歇性返回404且版本号显示不符问题排查
故障根因
- 核心判断依据是错误页返回的Nginx版本(1.18)和你部署的1.22版本不一致,说明服务器上同时运行了两个独立的Nginx进程:一个是Ubuntu 20.04默认apt源预装的1.18版本,另一个是你后续安装的1.22版本,两个进程都绑定了80端口。内核收到80端口的请求时,会按端口复用的负载规则随机分配给两个进程处理,才会出现间歇性正常、间歇性404的现象。
- 1.18版本的旧Nginx实例没有加载你配置的
api.website.comLaravel站点规则,请求落到这个实例时,匹配不到对应的server块,会走默认虚拟主机配置,默认主机根目录下没有你的项目文件,就会返回自带的1.18版本404错误页;请求落到1.22版本实例时,配置加载正常,就能正常访问站点。 - 你配置的
website.comNuxt反向代理之所以运行正常,大概率是两个Nginx实例都加载了这个站点的配置,或者旧实例的默认规则刚好能把请求转发到3000端口的Nuxt服务,所以不管请求落到哪个实例都能正常响应。
排查步骤
- 首先执行命令查看80端口的监听进程:
正常情况输出里只会有一个Nginx master进程,如果看到两个不同PID的Nginx master进程都绑定了80端口,直接坐实多实例问题。ss -tulnp | grep :80 - 确认两个Nginx进程的版本和路径:通过PID查看进程启动路径,执行
ls -l /proc/<PID>/exe就能看到对应进程的二进制文件位置,Ubuntu默认源安装的1.18版本Nginx二进制默认路径是/usr/sbin/nginx,第三方源/手动编译安装的1.22版本一般在/usr/local/nginx/sbin/nginx或者其他自定义路径。 - 分别校验两个实例的加载配置:对两个Nginx二进制执行
-T参数打印全量加载配置,比如/usr/sbin/nginx -T,就能看到旧的1.18实例确实没有加载api.website.com的站点配置,默认主机根目录也没有你的Laravel项目文件。 - 额外排查项:如果之前部署过Nginx容器,执行
docker ps | grep nginx检查是否有未关闭的Nginx容器映射了宿主机80端口,容器里的Nginx版本如果是1.18也会导致同类问题。
修复方案
- 先停掉不需要的旧Nginx实例:如果是apt安装的1.18版本,先确认对应的systemd服务关联的是旧实例,执行
systemctl stop nginx停服务,停完再跑一次ss -tulnp | grep :80确认只剩1.22版本的Nginx进程在监听80,此时连续刷新页面测试,应该不会再出现1.18版本的404页面。 - 彻底卸载旧版本避免开机自启冲突:执行
apt remove --purge nginx nginx-common nginx-core卸载系统自带的旧版本Nginx,卸载前注意备份好1.22版本的自定义配置,避免被误删。 - 为1.22版本Nginx配置正确的systemd服务,设置开机自启,执行
nginx -s reload重载配置后持续测试10分钟以上,确认所有请求都能正常响应。 - 如果排查发现是未关闭的Nginx容器导致的问题,直接停掉对应冗余容器,移除容器的80端口映射即可。
内容的提问来源于stack exchange,提问作者Capybarro
相关产品推荐
相关产品推荐

