避坑指南:Nginx 多层代理下的“404”与“重定向死循环”深度排查

目录

[避坑指南:Nginx 多层代理下的"404"与"重定向死循环"深度排查](#避坑指南:Nginx 多层代理下的“404”与“重定向死循环”深度排查)

[一、 问题现象](#一、 问题现象)

[二、 核心原因分析](#二、 核心原因分析)

[1. 优先级陷阱:正则匹配"劫持"了转发](#1. 优先级陷阱:正则匹配“劫持”了转发)

[2. 路径消失之谜:斜杠的艺术](#2. 路径消失之谜:斜杠的艺术)

[3. 协议丢失导致的重定向死循环](#3. 协议丢失导致的重定向死循环)

[三、 解决方案:标准转发模板](#三、 解决方案:标准转发模板)

[1. 外部网关(宝塔/站点)配置](#1. 外部网关(宝塔/站点)配置)

[2. Docker 打包与缓存清理](#2. Docker 打包与缓存清理)

[四、 排查工具箱](#四、 排查工具箱)

[五、 总结](#五、 总结)


避坑指南:Nginx 多层代理下的"404"与"重定向死循环"深度排查

在复杂的微服务或企业级应用部署中,我们经常使用多层 Nginx 架构:外层 Nginx(如宝塔面板)负责 HTTPS 卸载和全局入口,内层 Nginx(如 Docker 容器)负责业务逻辑分发。

最近在部署 MaxKey 认证系统(基于 Angular 开发)时,遇到了一个极其隐蔽的坑:后端 curl 正常,但域名访问静态资源报 404,且页面陷入重定向死循环。 本文将复盘排查过程并提供标准配置方案。

一、 问题现象

  1. 静态资源 404 :浏览器访问 [https://domain.com/maxkey/assets/js.js](https://domain.com/maxkey/assets/js.js) 报错 404,但直接在服务器 curl 内网 IP 资源却是通的。

  2. 重定向次数过多 :页面无法打开,提示 ERR_TOO_MANY_REDIRECTS

  3. Docker 缓存困惑:修改前端代码并重新打包镜像,发现页面内容始终不更新。

二、 核心原因分析

1. 优先级陷阱:正则匹配"劫持"了转发

这是宝塔等集成环境最常见的坑。宝塔默认会在站点配置中添加如下代码:

Nginx

复制代码
location ~ .*\.(js|css)?$ {
    expires      12h;
    # ...
}

Nginx 匹配规则是: 正则匹配(~)的优先级高于普通前缀匹配(location /maxkey/)。

当请求 .js 文件时,Nginx 会进入宝塔默认的正则块,试图在本地目录下找文件。由于文件实际在 9 号机的容器里,本地自然返回 404,转发逻辑根本没触发。

2. 路径消失之谜:斜杠的艺术

proxy_pass 中,结尾是否有斜杠 / 决定了路径是"替换"还是"透传":

  • proxy_pass http://ip/path/;(带斜杠):会切掉 location 匹配的部分。

  • proxy_pass http://ip;(不带斜杠):会完整保留路径转发。

  • 后果 :如果配置不当,后端收到的请求会变成 /assets/js(丢失了 /maxkey/),导致 Angular 路由因找不到 Base-Href 而崩溃。

3. 协议丢失导致的重定向死循环

外层走 HTTPS (443),内层走 HTTP (80)。如果外层没有告诉内层"用户实际用的是 HTTPS",内层 Nginx 可能会尝试发送 301 重定向让用户跳转到 HTTP,而外层又强制 HTTPS,从而导致无限循环。

三、 解决方案:标准转发模板

为了彻底解决上述问题,建议在外部网关(如宝塔)中使用 ^~(最佳前缀匹配)。它能强制跳过正则匹配,确保转发逻辑生效。

1. 外部网关(宝塔/站点)配置

Nginx

复制代码
# 使用 ^~ 确保优先级高于宝塔默认的 .js/.css 正则块
location ^~ /maxkey/ {
    # 显式指向内网业务服务器 IP 与端口
    proxy_pass http://10.130.135.9:8527/maxkey/; 

    # 关键头部透传
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    
    # 核心:告诉后端当前协议是 HTTPS,防止重定向循环
    proxy_set_header X-Forwarded-Proto $scheme;

    # 禁用可能导致冲突的自动重定向修改
    proxy_redirect off;
}

2. Docker 打包与缓存清理

如果您发现代码不更新,通常是 Docker 认为 dist 目录没有变化。请在构建时禁用缓存:

Bash

复制代码
# 强制重新拷贝 dist 目录
docker build --no-cache -t maxkey-frontend:latest .

# 启动时强制重新创建容器
docker-compose up -d --force-recreate maxkey-frontend

四、 排查工具箱

  • 抓包对比 :同时在两台机器执行 tail -f 观察日志,对比 GET 路径是否一致。

  • 无痕模式 :301 重定向会被浏览器深度缓存,修改配置后必须Ctrl+Shift+N 测试。

  • 配置校验 :修改 daemon.jsonnginx.conf 后,务必先用 nginx -t 或相关工具校验语法,再执行 reload

五、 总结

在处理多层代理时,优先级路径透明度协议识别 是三大核心。使用 ^~ 锁定路径优先级,配合 X-Forwarded-Proto 维持协议状态,可以解决 90% 以上的转发异常。


作者:Gao Song (高松)

场景:农业 AI 专利管理系统部署实践

相关推荐
Avan_菜菜2 小时前
FRP 内网穿透完整实战:从 HTTP 映射到 HTTPS 自签代理
运维·nginx·https
SelectDB1 天前
Litefuse 开源并推出单进程轻量模式,25 秒就能跑起来的 Agent 可观测与评估平台
运维·后端·自动化运维
XIAOHEZIcode2 天前
Linux系统鼠标偏移常见原因以及修复方案
linux·运维·游戏
用户0328472220703 天前
如何搭建本地yum源(上)
运维
ping某4 天前
为什么 Nginx 明明监听了 80,转发后端时却用了 4xxxx 端口?
后端·nginx
大树886 天前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠6 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
霸道流氓气质6 天前
领域驱动设计(DDD)在 Spring Boot 微服务中的实践指南
运维·spring boot·微服务
Inhand陈工6 天前
基于台达PLC与映翰通IG502的智慧水产养殖精准投喂与远程运维解决方案
运维·人工智能·物联网·阿里云·信息与通信
酣大智6 天前
ARP代理--工作原理
运维·网络·arp·arp代理