大家好我是舒一笑不秃头,喜欢写作和分享,更多精彩内容~
一句话总结:前端路径前缀、网关转发前缀、后端真实路径 这三件事如果没彻底对齐,线上一定会"随机炸"。
1. 背景:看起来只是改个前缀,实际上是链路重构
项目原来跑在 /ais,现在要挂到网关 :8000/kb/。
同时后端有两套服务:
- 主后端:
188.104.159.164:10003 - 预览服务:
188.104.159.164:8012
前端请求统一走 /aiskb/...,再由 Nginx 分发到不同 upstream。
2. 我遇到的典型故障(你大概率也会遇到)
-
502 Connection refused原因:容器里转发到了
127.0.0.1:10003,但后端不在容器内。 -
405 Not Allowed原因:请求没命中 API location,掉进了静态
location /kb/,POST 被静态资源处理逻辑拒绝。 -
413 Request Entity Too Large原因:Nginx 默认 body 太小(常见 1m)。
-
前端登录页
404原因:后端返回
Location: /login,但前端实际部署在/kb/login。 -
/kb/license/validate被重写成/license/validate原因:rewrite 写猛了,把后端真实需要的
/kb也干掉了。 -
预览接口走错后端
原因:
/kl/api/saas/element/preview/*应该去8012,却被通用规则发到10003。 -
以为是 Host 丢失导致 405
结论:不是。405 多数是路由命中错误,不是 Host 头问题。
3. 核心原则(非常关键)
- 前端前缀、网关前缀、后端真实路径,必须逐条列清楚。
- 精确路由必须放在通用路由之前(
^~+ 顺序)。 - 只改该改的前缀,不要全局无脑 rewrite。
- 登录跳转要做
proxy_redirect或兜底重定向兼容。 - 上传场景必须显式设置
client_max_body_size。
4. 可直接落地的 Nginx 配置(我线上用的结构)
nginx
upstream ais_backend {
server 188.104.159.164:10003;
}
upstream ais_preview {
server 188.104.159.164:8012;
}
server {
listen 8000;
server_name _;
root /usr/share/nginx/html;
index index.html index.htm;
client_max_body_size 2g;
location = / { return 301 /kb/; }
location = /kb { return 301 /kb/; }
# 预览服务:必须放在通用 /aiskb/ 之前
location ^~ /aiskb/kl/api/saas/element/preview/ {
rewrite ^/aiskb/(.*)$ /$1 break;
proxy_pass http://ais_preview;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# 通用 API
location ^~ /aiskb/ {
rewrite ^/aiskb/(.*)$ /$1 break;
proxy_pass http://ais_backend;
proxy_redirect ~^/(login|register|sso|home)(/.*)?$ /kb/$1$2;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# 兼容后端真实需要 /kb 的接口(不要 rewrite 掉 /kb)
location ^~ /kb/license/ {
proxy_pass http://ais_backend;
proxy_redirect ~^/(login|register|sso|home)(/.*)?$ /kb/$1$2;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# 后端静态兼容
location ^~ /kb/ais/ {
rewrite ^/kb/(ais/.*)$ /$1 break;
proxy_pass http://ais_backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location ^~ /ais/ {
proxy_pass http://ais_backend;
proxy_redirect ~^/(login|register|sso|home)(/.*)?$ /kb/$1$2;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# 后端返回 /login 时的前端兼容
location ~ ^/(login|register|sso|home)(/.*)?$ {
return 302 /kb$uri$is_args$args;
}
# 前端 SPA
location /kb/ {
rewrite ^/kb/(.*)$ /$1 break;
try_files $uri $uri/ /index.html;
}
}
5. 排错顺序(建议收藏)
- 先看浏览器 Network:状态码 + Request URL + Method。
- 再看 Nginx access/error:确认实际命中的 location 和 upstream。
- 再核对 rewrite 前后 URI 是否符合后端 Controller。
- 大文件上传先排 Nginx
413,再排后端 multipart 限制。 - 登录跳转问题优先看
Location响应头。
6. 最后一句
这类问题本质不是"会不会写 Nginx",而是你有没有把 路径语义 设计清楚。
只要把"入口路径、网关路径、后端真实路径、重写规则、优先级"画成一张表,80% 的线上故障都能提前消失。