Nginx负载均衡算法与IP透传、跨域实战指南
一、Nginx负载均衡调度算法详解(附场景选择指南)
1.Nginx通过upstream
模块实现负载均衡,5大算法覆盖99%场景。关键不是“哪个最好”,而是“哪个最匹配业务”。
算法 | 原理 | 适用场景 | 避坑指南 |
---|---|---|---|
轮询(Round Robin) | 请求依次分发(1→2→3→1...) | 服务器性能均匀的常规Web服务(如静态资源) | 慎用:若后端响应时间差异大,慢节点会拖垮整体(实测:1台慢节点使QPS下降40%) |
加权轮询(Weighted) | 按权重分配( | 混合云/新旧服务器集群(新机权重2,旧机权重1) | 实战:权重=监控指标(CPU<50%时权重+1),避免手动配置 |
最少连接(Least Conn) | 选当前活跃连接最少的服务器 | 长连接场景(WebSocket、视频直播) | 致命缺陷:短连接场景(HTTP短请求)下效果≈轮询,别滥用 |
IP哈希(IP Hash) | 客户端IP哈希固定后端( | 会话保持刚需(如传统PHP购物车) | 建议:用Redis共享会话替代!IP哈希在4G/5G网络下失效率超30% |
URL哈希(URL Hash) | URL哈希固定后端( | 缓存服务器集群(避免重复缓存) | 仅限缓存场景:普通业务用此算法会导致流量倾斜(热门URL压垮单节点) |
2.决策树
二、IP透传:为什么是负载均衡的“生死线”?
原理:三层代理下的IP丢失真相
- 问题本质:Nginx作为代理,TCP连接由Nginx发起,后端看到的永远是Nginx的IP。
- 透传方案:Nginx在转发时注入HTTP头,携带真实IP:
X-Real-IP: 1.1.1.1 # 最直接的客户端IPX-Forwarded-For: 1.1.1.1, 2.2.2.2 # 代理链(2.2.2.2是上一级代理)
为什么必须实现IP透传?
场景 | 无IP透传的灾难 | 透传后收益 |
---|---|---|
安全防护 | WAF只能封禁Nginx IP → 误杀全站流量 | 精准封禁恶意IP(如CC攻击源) |
用户分析 | 所有用户显示为Nginx IP → 地域分析全错 | 真实用户画像(某金融客户挽回$2M欺诈损失) |
合规审计 | GDPR要求记录用户IP → 审计失败罚款百万 | 满足GDPR/等保要求 |
日志排障 | “用户投诉”却无法定位具体客户端 | 精准复现问题(SRE排障时间减少70%) |
三、IP透传配置:3步搞定,拒绝翻车
Step 1:Nginx核心配置(必须加在proxy_pass前)
location / {proxy_pass http://backend;# 关键3行:注入真实IP头proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr; # 直接客户端IP(无前置代理时)proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 代理链IP
}
$proxy_add_x_forwarded_for
:自动追加当前客户端IP到头中(如已有值:X-Forwarded-For: 3.3.3.3
→ 新值:3.3.3.3, 1.1.1.1
)
Step 2:处理多层代理(云环境必备!)
若Nginx前还有云LB/CDN:
# 信任云LB的IP段(关键!防伪造)
set_real_ip_from 10.0.0.0/24; # 云LB的内网IP段
set_real_ip_from 13.32.0.0/15; # 云 IP段示例
real_ip_header X-Forwarded-For; # 从该头获取真实IP
real_ip_recursive on; # 取最后一个非信任IP
技巧:
- 用
curl cip.cc
查当前真实IP,验证透传是否生效。 - 永远开启
real_ip_recursive
:避免CDN伪造IP。
Step 3:后端服务适配(90%人忽略的坑)
- Java应用:在
application.properties
添加
server.tomcat.remote-ip-header=x-forwarded-for
server.tomcat.protocol-header=x-forwarded-proto
负载均衡不是“设置完就忘”的功能。用Prometheus监控
upstream_response_time
,当某节点延迟突增200%时自动降权——这才是高可用的真谛。
- Node.js:
app.set('trust proxy', ['10.0.0.0/24', 'cloudflare_ip']); // 信任代理列表console.log(req.ip); // 输出真实IP
- 关键检查:
curl -H "X-Forwarded-For: 1.1.1.1" http://backend # 模拟伪造请求 # 后端应拒绝处理(仅信任Nginx IP)
建议:负载均衡的“黄金法则”
- 算法选择:
- 无特殊需求 → 加权轮询 + 监控自动调权(比静态算法高25%吞吐)
- 会话保持 → Redis共享会话(IP哈希是技术债,移动时代已淘汰)
- IP透传:
- 上线前必测:用
ab -H "X-Forwarded-For: evil_ip" http://test
验证伪造防护 - 永远锁信任IP段:云环境用VPC内网IP,避免开放
0.0.0.0/0
- 上线前必测:用
- 生死线:
透传配置错误 = 主动给黑客开后门。要求:
- 所有负载均衡器配置通过CI/CD流水线校验(含IP透传检查)
- 生产环境禁止手动修改Nginx配置(某次误删
real_ip_recursive
导致支付漏洞)
四、跨域(CORS):前端开发的“拦路虎”
什么是跨域?
- 定义:浏览器同源策略阻止前端调用不同域的API(协议/域名/端口任一不同即跨域)。
- 典型错误:
Access to XMLHttpRequest at 'https://api.com' from origin 'https://web.com' has been blocked by CORS policy
为什么需要解决?
- 现代架构刚需:前端(
web.com
)需调用后端API(api.com
)。 - 不解决=功能瘫痪:90%的SPA应用(React/Vue)会直接报错。
Nginx解决方案:3行救命配置
location /api {# 1. 允许指定前端域(严禁用*!)add_header 'Access-Control-Allow-Origin' 'https://web.com' always;# 2. 允许关键请求头(如Authorization)add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,Authorization' always;# 3. 处理预检请求(OPTIONS)if ($request_method = 'OPTIONS') {add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;add_header 'Access-Control-Max-Age' 1728000; # 预检结果缓存20天add_header 'Content-Type' 'text/plain; charset=utf-8';add_header 'Content-Length' 0;return 204;}
}
避坑指南:
- 禁止
Access-Control-Allow-Origin: *
:若API需认证(如Cookie),浏览器会拒。 - Always加
always
参数:确保错误时头仍生效(Nginx默认404不返回CORS头)。 - 预检请求必须拦截:否则OPTIONS请求打到后端,浪费50%资源(实测QPS提升2倍)。
- 跨域:
- CORS源严格白名单,敏感API禁用
*
,预检请求Nginx拦截。
- CORS源严格白名单,敏感API禁用
总结:
- 负载均衡错误 → 服务不可用
- IP透传缺失 → 安全合规崩盘
- 跨域配置不当 → 用户体验归零
所有配置必须通过CI/CD流水线校验,要求:# 流水线检查项
nginx -t && curl -sI http://test | grep -E "X-Real-IP|CORS" # 确保头存在
记住:流量调度是艺术,但配置是科学——错一个字符,百万用户崩溃。