Nginx upstream 负载均衡 404,单节点转发正常的根因与解决

一、问题现象

  1. 核心配置
    nginx

后端节点集群配置

upstream backend_servers {

server 192.168.1.10:8080;

server 192.168.1.11:8080;

server 192.168.1.12:8080;

}

server {

listen 80;

server_name 192.168.1.30;

复制代码
client_max_body_size 50M;     
 
location / {
    root   /usr/share/nginx/html/admin;
    index  index.html index.htm;
    try_files $uri $uri/ /index.html; 
}    
   
# 异常的接口转发配置
location /admin-api/ {     
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;   
    proxy_pass http://backend_servers;
}

}

  1. 问题表现

访问 http://192.168.1.30/admin-api/server/ 前缀的接口,持续返回 404;

若将 proxy_pass http://backend_servers; 替换为单节点 proxy_pass http://192.168.1.12:8080;,接口可正常访问;

单独测试集群内每台后端节点(192.168.1.10/11/12:8080)的 admin-api/server/ 接口,均返回正常,无 404 问题。

二、排查过程

  1. 初步排除常见问题
    排除后端节点故障:所有节点单独访问接口正常,无服务未启动 / 接口缺失问题;
    排除路径拼接问题:单节点转发未加尾斜杠仍正常,说明后端支持 /admin-api/server/ 完整路径;
    排除网络连通性:Nginx 服务器可正常 telnet 所有后端节点的 8080 端口,无防火墙拦截。
  2. 关键验证:模拟 upstream 转发请求
    通过 curl 模拟 Nginx upstream 的转发行为,发现核心差异:
    bash
    运行

模拟upstream转发(带Host: backend_servers),返回404

curl -v -H "Host: backend_servers" http://192.168.1.12:8080/admin-api/server/

模拟单节点转发(带Host: 192.168.1.12:8080),返回正常

curl -v -H "Host: 192.168.1.12:8080" http://192.168.1.12:8080/admin-api/server/

结论:upstream 模式下 Nginx 默认传递的 Host 头异常,导致后端服务识别失败。

三、根因分析

Nginx upstream 转发时,若未显式配置proxy_set_header Host,会默认将Host头设置为 upstream 集群名称(如backend_servers),而非客户端请求的 Host 或后端节点的 IP: 端口。

后端服务通常依赖Host头做路由匹配、域名鉴权或反向代理识别,当收到Host: backend_servers这种非预期值时,会判定为非法请求,返回 404;而单节点转发时,Nginx 隐式传递Host: 后端IP:端口,后端能正常识别,因此请求成功。

四、解决方案

  1. 核心修复:显式配置 Host 头
    在接口转发的 location 块中添加proxy_set_header Host host;,强制传递客户端请求的 Host 头(或后端识别的固定 Host): nginx location /admin-api/ { proxy_set_header X-Real-IP remote_addr;
    proxy_set_header X-Forwarded-For proxy_add_x_forwarded_for; proxy_set_header Host host; # 关键:传递客户端请求的Host(如192.168.1.30)

    若后端需固定Host,可替换为:proxy_set_header Host "192.168.1.12:8080";

    proxy_pass http://backend_servers;
    }

  2. 配置生效
    bash
    运行

检查配置语法

nginx -t

平滑重启Nginx

nginx -s reload

  1. 生产环境优化(可选)

为避免后续节点故障 / 异常导致 404,补充 upstream 健康检查和连接优化:

nginx

upstream backend_servers {

server 192.168.1.10:8080 max_fails=3 fail_timeout=10s;

server 192.168.1.11:8080 max_fails=3 fail_timeout=10s;

server 192.168.1.12:8080 max_fails=3 fail_timeout=10s;

keepalive 32; # 长连接优化

}

location /admin-api/ {

proxy_set_header X-Real-IP $remote_addr;

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

proxy_set_header Host $host;

proxy_http_version 1.1; # 强制HTTP/1.1,避免连接兼容问题

proxy_pass http://backend_servers;

}

五、总结

Nginx upstream 负载均衡与单节点转发的核心差异之一是Host头的默认传递规则,当出现「单节点正常、集群 404」且后端节点无故障时,优先排查:

是否缺失Host头配置;

是否有其他关键请求头(如 X-Forwarded-Host)未传递;

upstream 集群名称是否被后端服务拦截。

显式配置proxy_set_header Host $host;是解决此类问题的关键,也是 Nginx 反向代理的最佳实践(避免依赖默认行为)。

相关推荐
judezh11 分钟前
api 容器一直 unhealthy?我把一个 Agent 运行时的健康检查逐条拆了,查出四个问题
运维·docker
春天花会开13122 分钟前
内网 HTTPS 部署实战:私有 CA + Nginx 反向代理全流程复盘
运维·nginx·https
AllFiles26 分钟前
K8s Node Exporter 异常 Write 超时排查实录
运维·后端·kubernetes
虎头金猫5 天前
4K 视频总卡在公网带宽?用 N1 + OpenList 把网盘播放链路重新理顺
运维·服务器·网络·python·容器·beautifulsoup·pandas
还是大剑师兰特5 天前
解决nginx错误:http://localhost:7000正常,http://localhost:7000/map 报错404
nginx·大剑师
AI职业加油站5 天前
AI智能体应用工程师证书:政策红利下的职业新风口
大数据·运维·人工智能·学习·职场发展
此冬歌咏6 天前
K8s 节点故障实战:优雅驱逐 31 秒,硬故障 331 秒,以及那个永远 Pending 的 Pod
运维·k8s
xing-xing6 天前
Docker容器中Nginx站点根目录网页配置访问
nginx·docker
-梅6 天前
linux(8) 软硬链接
linux·运维·服务器
张洛闻Eren6 天前
k8s云原生【第十课】:水平 Pod 自动扩缩容
运维·数据库·云原生·kubernetes·github