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 反向代理的最佳实践(避免依赖默认行为)。

相关推荐
开开心心_Every21 小时前
Win10/Win11版本一键切换工具
linux·运维·服务器·edge·pdf·web3·共识算法
啟明起鸣21 小时前
【Nginx 网关开发】从源码分析 Nginx 的多进程启动原理
运维·nginx
怣5021 小时前
Linux创意命令组合:让终端变得有趣又高效
linux·运维·服务器
啟明起鸣21 小时前
【Nginx 网关开发】上手 Nginx,简简单单启动一个静态 html 页面
运维·c语言·前端·nginx·html
MACKEI21 小时前
服务器流式传输接口问题排查与解决方案
python·nginx·流式
Tinyundg21 小时前
Linux系统分区
linux·运维·服务器
要做一个小太阳1 天前
华为Atlas 900 A3 SuperPoD 超节点网络架构
运维·服务器·网络·华为·架构
江畔何人初1 天前
service发现
linux·运维·云原生
life码农1 天前
Linux系统清空文件内容的几种方法
linux·运维·chrome
zbguolei1 天前
虚拟机安装Ubuntu后无法登录
linux·运维·ubuntu