什么是负载均衡?
负载均衡(Load Balancing) 就是把请求分发给多台后端服务器处理,避免单台服务器压力过大。
- 高可用:某台后端挂了,请求自动转发到其他服务器
- 高并发:多台服务器一起扛流量
- 易扩展:流量大了加服务器就行
基本使用:proxy_pass
最简单的写法,直接在 proxy_pass 填后端地址:
server {
listen 80;
location / {
proxy_pass http://192.168.1.10:8080;
}
}
但这种方式不支持故障转移,仅适合开发测试。
生产配置:upstream 块
把后端服务器定义在 upstream 块中,server 块引用它。upstream 和 server 同级,都放在 http 里:
http {
upstream blog_servers {
server 192.168.1.10:8080;
server 192.168.1.11:8080;
server 192.168.1.12:8080;
}
server {
listen 80;
server_name blog.example.com;
location / {
proxy_pass http://blog_servers;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
}
六大负载均衡算法
默认是轮询,可以通过配置切换到其他算法。
1. 轮询(Round Robin)
请求按顺序轮流分发到每台后端。什么都不配就是轮询:
upstream backend {
server 192.168.1.10:8080;
server 192.168.1.11:8080;
server 192.168.1.12:8080;
}
适用:后端配置相同、处理时间相近的场景。不适用:后端性能差异大或响应时间波动大的场景。
2. 权重(Weight)
用 weight 控制请求比例,数字越大分到的越多:
upstream backend {
server 192.168.1.10:8080 weight=3;
server 192.168.1.11:8080 weight=2;
server 192.168.1.12:8080 weight=1;
}
两个辅助参数:
down:标记下线,运维维护时用backup:备用节点,主节点全挂了才启用
upstream backend {
server 192.168.1.10:8080 weight=3;
server 192.168.1.11:8080 weight=2;
server 192.168.1.12:8080 backup;
server 192.168.1.13:8080 down;
}
3. IP Hash(ip_hash)
同一个客户端 IP 始终转发到同一台后端。解决 Session 保持问题——如果应用把用户会话存在本地内存,请求跳到别的服务器会话就丢了。
upstream backend {
ip_hash;
server 192.168.1.10:8080;
server 192.168.1.11:8080;
server 192.168.1.12:8080;
}
注意:NAT 环境下多用户共享同一出口 IP,会导致负载不均;某台后端宕机时,它上面的用户会话会全部丢失。
4. Least Connections(least_conn)
转发给当前活跃连接数最少的服务器:
upstream backend {
least_conn;
server 192.168.1.10:8080;
server 192.168.1.11:8080;
server 192.168.1.12:8080;
}
适用:长连接场景(WebSocket、gRPC),避免连接堆积。注意:连接数少不代表负载轻。
5. URL Hash
根据请求的 URL 做 Hash,相同 URL 始终转发到同一台后端,适合做缓存亲和:
upstream backend {
hash $request_uri;
server 192.168.1.10:8080;
server 192.168.1.11:8080;
server 192.168.1.12:8080;
}
适用:CDN 回源、资源类请求。注意:增减节点会导致 URL 重新映射,缓存可能大面积失效。
6. Fair(第三方模块)
根据后端响应时间分发,响应快的分到更多请求。需额外安装 ngx_http_upstream_fair_module:
upstream backend {
fair;
server 192.168.1.10:8080;
server 192.168.1.11:8080;
server 192.168.1.12:8080;
}
注意:该模块多年未更新,不兼容 Nginx 1.17+,不推荐在生产环境使用。
常见配置参数
故障转移
upstream backend {
server 192.168.1.10:8080 max_fails=3 fail_timeout=30s;
server 192.168.1.11:8080 max_fails=3 fail_timeout=30s;
}
max_fails=3:30 秒内失败 3 次,标记为不可用fail_timeout=30s:标记不可用后,等待 30 秒再尝试恢复
proxy_next_upstream
遇到后端报错时自动切换到下一台:
location / {
proxy_pass http://backend;
proxy_next_upstream error timeout http_500 http_502 http_503;
proxy_next_upstream_tries 2;
}
企业级方案(思路)
上面讲的算法都是静态配置——后端变了就得改配置文件然后 reload。在微服务或容器环境下(后端频繁扩缩容),这种方式不现实。
生产环境的思路是:
- OpenResty + Lua 脚本:通过
balancer_by_lua_block在运行时动态选择后端,配合健康检查自动摘除故障节点,新增节点也不需要 reload - nginx-upsync-module + Consul:从 Consul 拉取后端列表,自动更新 upstream
- Nginx Plus 商业版:内置动态 upstream 管理 API 和主动健康检查,花钱省事
这些方案需要 Lua 或服务注册发现的知识,属于进阶内容,这里只提概念不展开。
总结
| 算法 | 配置指令 | 适用场景 |
|---|---|---|
| 轮询 | 默认 | 后端配置相同,请求处理时间相近 |
| 权重 | weight | 服务器配置不同,按能力分配 |
| IP Hash | ip_hash | 需 Session 保持 |
| Least Connections | least_conn | 长连接、WebSocket |
| URL Hash | hash $request_uri | 缓存亲和、CDN 回源 |
| Fair | fair(第三方) | ⚠️ 不推荐生产使用 |
快速自检
- ✅ 能写出 upstream + proxy_pass 的基础配置
- ✅ 知道六种算法的配置指令和各自适用场景
- ✅ 知道
max_fails、fail_timeout的用法 - ✅ 知道
proxy_next_upstream做故障转移 - ✅ 知道内置算法都是静态配置,企业场景需要动态方案