在分布式系统中,Nginx 负载均衡是入门必学、线上必用的核心技能。这篇文章用"实战配置 + 场景选型"的思路,帮你快速掌握。
🎯 一、负载均衡做什么?
当你有多台后端服务器时,Nginx 作为入口,把外部请求按一定规则分发到不同后端,实现:
-
水平扩展:加机器就能扛更多流量。
-
高可用:某台后端挂了,自动切到健康节点。
-
灵活调度:按性能、会话、连接数等策略分发。
核心模块就两块:
"ngx_http_upstream_module":定义后端服务器组(upstream)。
"ngx_http_proxy_module":把请求转发过去(proxy_pass)。
⚙️ 二、基础配置骨架
一个最小可用的负载均衡配置长这样:
http {
1. 定义后端服务器组
upstream myapp {
server 192.168.1.101:8080;
server 192.168.1.102:8080;
server 192.168.1.103:8080;
}
server {
listen 80;
server_name your-domain.com;
location / {
2. 反向代理到 upstream
proxy_pass http://myapp;
3. 透传关键头部(真实IP、Host等)
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
}
"upstream" 定义一组后端,
"proxy_pass" 引用组名即可实现负载均衡。
- 默认策略是加权轮询(weight=1),请求依次分发到 101→102→103→101...
📊 三、常用负载均衡策略
不同场景选不同策略,都在 upstream 里配:
- 轮询(Round Robin)------ 默认
不加任何策略就是轮询,请求依次轮流发到各后端。适合后端配置相近、无状态的短请求。
- 加权轮询(Weighted Round Robin)
upstream myapp {
server 192.168.1.101:8080 weight=3; # 高配机,多扛流量
server 192.168.1.102:8080 weight=2; # 中配
server 192.168.1.103:8080 weight=1; # 低配/测试机
}
按权重比例分发,weight 越高分到的请求越多。常用于机器配置不均、灰度发布等场景。
- IP 哈希(IP Hash)------ 会话保持
upstream myapp {
ip_hash; # 同一客户端 IP 固定打到同一后端
server 192.168.1.101:8080;
server 192.168.1.102:8080;
}
基于客户端 IP 做哈希,确保同一用户请求落到同一台后端。适合 Session 未共享、有本地缓存的场景。注意:一般不与 weight 混用,且后端增减会导致部分会话失效。
- 最少连接数(Least Connections)
upstream myapp {
least_conn;
server 192.168.1.101:8080;
server 192.168.1.102:8080;
}
优先发给当前活跃连接数最少的后端。适合请求处理时间差异大、长耗时任务多的场景(如大文件上传、复杂计算)。
- 其他高级策略
- URL 哈希:
"hash $request_uri",相同 URL 打到同一后端,提高缓存命中。
- fair / 响应时间优先:多为第三方模块,按响应速度动态调度,非 Nginx 官方内置。
🩺 四、健康检查与故障转移
生产环境必须配,否则后端挂了 Nginx 还会继续转发,造成 502/504。
被动检查(Nginx 开源版标配)
upstream myapp {
server 192.168.1.101:8080 max_fails=3 fail_timeout=30s;
server 192.168.1.102:8080 max_fails=3 fail_timeout=30s;
}
location / {
proxy_pass http://myapp;
连接错误/超时自动重试到下一台,也可加上 http_500/502/503
proxy_next_upstream error timeout;
}
"max_fails":在
"fail_timeout" 内失败几次标记为不可用。
"fail_timeout":标记不可用后的停用时间,过后自动探活恢复。
- 默认只对网络级错误(连接拒绝、超时)计数,HTTP 5xx 不算失败,可通过
"proxy_next_upstream" 扩展。
主动健康检查(商业版/Tengine)
开源 Nginx 原生不支持主动探活,但 Tengine / Nginx Plus 支持:
upstream myapp {
zone myapp 64k;
server 192.168.1.101:8080;
server 192.168.1.102:8080;
}
server {
location / {
proxy_pass http://myapp;
health_check interval=5s fails=3 passes=2;
}
}
定期主动发请求检查后端健康,比被动更及时。
🔧 五、生产级完整示例
结合策略、健康检查和超时控制的实用配置:
http {
upstream backend {
策略:最少连接,带权重
least_conn;
主节点
server 192.168.1.101:8080 weight=3 max_fails=3 fail_timeout=30s;
server 192.168.1.102:8080 weight=2 max_fails=3 fail_timeout=30s;
备份节点,主节点全挂时启用
server 192.168.1.103:8080 backup;
}
server {
listen 80;
server_name api.your-app.com;
location / {
proxy_pass http://backend;
透传真实 IP/Host
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
超时控制(按后端 P99 响应调整)
proxy_connect_timeout 5s;
proxy_send_timeout 10s;
proxy_read_timeout 60s;
错误重试:网络错 + 5xx,最多试 2 次
proxy_next_upstream error timeout http_500 http_502 http_503;
proxy_next_upstream_tries 2;
}
}
}
💡 六、常见坑与避雷
- Session 共享:用了
"ip_hash" 就别随便增删后端节点;推荐直接用 Redis 集中存 Session,更灵活。
-
健康检查不够细:被动检查依赖真实流量,关键时刻可能不及时;重要业务考虑 Tengine / Nginx Plus 主动检查或接入外部服务发现。
-
超时设太小:导致大量 502/504,建议按后端接口 P99 响应时间的 1.5~2 倍配置超时。
-
重试非幂等请求:
"proxy_next_upstream" 默认只对 GET/HEAD 等幂等方法生效,POST 重试可能导致重复下单,慎配。
如果你告诉我你的具体场景(比如 Java/Go 应用、是否有 Session、想用什么策略),我可以给你一份更贴合业务的精简配置。