Nginx 负载均衡
负载均衡(Load Balancing)是分布式系统中的核心技术,它通过将网络流量合理分配到多个服务器,实现资源优化、吞吐量提升和容错能力增强。当系统面临大量用户访问,负载过高的时候,通常会使用Nginx增加服务器数量来进行横向扩展,然后将请求分发到各个服务器上。
Nginx作为负载均衡解决方案具有以下显著优势:
- 高性能事件驱动架构:基于epoll/kqueue的异步非阻塞模型,能够处理数百万并发连接
- 灵活的负载算法:支持轮询、加权轮询、IP哈希、最少连接等多种内置分发策略
- 动态配置能力:支持运行时上游服务器组更新,无需重启服务
- 健康检查机制:通过被动或主动方式自动屏蔽故障节点,提高系统可靠性
- 协议支持广泛:可实现HTTP、HTTPS、TCP和UDP等多种协议的负载均衡
基本配置结构
Nginx负载均衡配置主要涉及两个核心模块:upstream和server。upstream模块用于定义后端服务器组,而server模块中的location配置则通过proxy_pass指令将请求转发到上游服务器组。
http {
upstream backend {
# 默认轮询策略
server 192.168.1.101:8080;
server 192.168.1.102:8080;
server 192.168.1.103:8080;
}
server {
listen 80;
location / {
proxy_pass http://backend;
proxy_set_header Host $host;
}
}
}- proxy_pass:核心指令,用于将请求转发到上游服务器组,值是upstream定义的名称
- proxy_set_header:修改转发给后端服务器的请求头,常见设置包括:
- Host $host:保留原始请求的主机头
- X-Real-IP $remote_addr:传递客户端真实IP
- X-Forwarded-For $proxy_add_x_forwarded_for:记录请求经过的代理服务器链
- upstream:定义后端服务器池,支持多种参数:
- server:后端服务器地址,格式为host:port
- weight:权重值,用于加权轮询
- max_fails和fail_timeout:健康检查相关参数
负载均衡算法
轮询算法(Round Robin)
原理:默认算法,请求按时间顺序均匀分配到各个服务器。
配置示例:
upstream backend {
server 192.168.1.101:8080;
server 192.168.1.102:8080;
}特点:
- 优点:简单公平,适用于后端服务器性能相近的场景
- 缺点:不考虑服务器实际负载,性能差异大时可能导致负载不均
适用场景:后端服务器配置相同且无状态服务的简单应用
加权轮询(Weighted Round Robin)
原理:在轮询基础上,根据服务器性能分配权重,权重高的服务器接收更多请。
配置示例:
upstream backend {
server 192.168.1.101:8080 weight=3; # 60%流量
server 192.168.1.102:8080 weight=2; # 40%流量
}特点:
- 优点:根据服务器实际性能合理分配请求,提高资源利用率
- 缺点:静态权重,无法适应服务器负载的动态变化
适用场景:服务器性能不均(如CPU/内存差异)的环境
IP哈希(IP Hash)
原理:根据客户端IP计算哈希值,相同IP的请求固定分配到同一台服务器。
配置示例:
upstream backend {
ip_hash;
server 192.168.1.101:8080;
server 192.168.1.102:8080;
}特点:
- 优点:解决会话保持问题,避免用户在不同服务器间切换导致的会话丢失
- 缺点:在客户端使用NAT或大量请求来自同一IP时会导致负载不均
适用场景:需要会话保持的应用(如购物车、登录状态)
最少连接(Least Connections)
原理:将请求优先分配给当前连接数最少的服务器。
配置示例:
upstream backend {
least_conn;
server 192.168.1.101:8080;
server 192.168.1.102:8080;
}特点:
- 优点:考虑服务器实际负载,使负载分配更加均衡
- 缺点:计算开销略大于简单轮询
适用场景:长连接服务(如WebSocket、数据库连接池)
随机算法 (Random)
原理:随机选择后端服务器
upstream backend {
random;
server backend1.example.com;
server backend2.example.com;
}URI哈希(URI Hash)
原理:根据请求URI分配流量,相同URI始终到同一服务器。
配置示例:
upstream backend {
hash $request_uri consistent;
server 192.168.1.101:8080;
server 192.168.1.102:8080;
}特点:
- 优点:提高缓存命中率,优化资源使用
- 缺点:需要安装第三方模块(ngx_http_upstream_hash_module)
适用场景:缓存优化(如CDN边缘节点)
fair
比 weight、ip_hash更加智能的负载均衡算法,fair算法可以根据页面大小和加载时间长短智能地进行负载均衡,也就是根据后端服务器的响应时间 来分配请求,响应时间短的优先分配。
fair是Nginx的一个第三方负载均衡算法,不是Nginx官方自带的模块,需要通过第三方模块nginx-upstream-fair来实现
安装
# 下载模块
git clone https://github.com/gnosek/nginx-upstream-fair.git
# 编译Nginx时添加模块
./configure --add-module=/path/to/nginx-upstream-fair
make && make install配置
upstream backend {
fair;
server backend1.example.com;
server backend2.example.com;
server backend3.example.com;
}特点:
优点:更智能的负载分配,避免服务器过载自动适应后端服务器性能变化
缺点:需要额外安装第三方模块,相比简单算法有轻微性能开销
算法选择决策指南
- 无状态服务:轮询或加权轮询(服务器性能不一时)
- 会话保持需求:IP哈希或Cookie绑定
- 长连接服务:最少连接算法
- 缓存优化:URI哈希或通用哈希
- 动态负载适应:商业版Nginx Plus的基于响应时间算法
负载均衡代理参数
server {
...
upstream example.com {
server 192.168.10.1:8080;
}
server {
proxy_pass http://example.com;
# 可引入支持的代理参数
include proxy.conf;
}
...
}核心代理指令
proxy_pass:
nginxproxy_pass http://backend_server;- 定义后端服务器地址,可以是域名、IP或upstream名称
- 注意:URL结尾是否带
/会影响URI传递方式
proxy_set_header:
nginxproxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;- 修改转发给后端服务器的请求头
- 生产环境必须设置的关键头:
Host:保留原始请求的主机名X-Real-IP:传递客户端真实IPX-Forwarded-For:记录请求经过的代理链
连接控制参数
proxy_connect_timeout:
nginxproxy_connect_timeout 5s;- 与后端服务器建立连接的超时时间
- 生产建议:3-10秒,根据网络状况调整
proxy_send_timeout:
nginxproxy_send_timeout 15s;- 发送请求到后端服务器的超时时间
- 生产建议:10-30秒,取决于请求大小
proxy_read_timeout:
nginxproxy_read_timeout 30s;- 从后端服务器读取响应的超时时间
- 生产建议:30-60秒,API服务可适当缩短
缓冲区配置
proxy_buffer_size:
nginxproxy_buffer_size 4k;- 设置从后端服务器读取的第一部分响应缓冲区大小
- 通常包含响应头
proxy_buffers:
nginxproxy_buffers 8 16k;- 设置用于读取响应的缓冲区数量和大小
- 格式:
数量 大小 - 生产建议:
8-16 16k-32k,根据平均响应大小调整
proxy_busy_buffers_size:
nginxproxy_busy_buffers_size 32k;- 当缓冲区满时,限制可以标记为"busy"的缓冲区大小
- 通常设置为
proxy_buffers中单个缓冲区大小的2倍
连接复用
proxy_http_version:
nginxproxy_http_version 1.1;- 与后端服务器通信使用的HTTP协议版本
- 必须1.1才能启用keepalive
proxy_set_header Connection:
nginxproxy_set_header Connection "";- 清空Connection头,启用keepalive
upstream keepalive:
nginxupstream backend { server 10.0.0.1:8080; keepalive 32; }- 保持到后端服务器的长连接数量
- 生产建议:根据并发量设置32-256
请求头控制
proxy_hide_header:
nginxproxy_hide_header X-Powered-By;- 隐藏后端服务器返回的特定响应头
- 常用于隐藏服务器信息,增强安全性
proxy_pass_header:
nginxproxy_pass_header Server;- 允许传递后端服务器设置的特定响应头
重定向处理
proxy_redirect:
nginxproxy_redirect off; proxy_redirect http://backend https://frontend;- 修改后端返回的重定向Location头
- 生产环境建议:关闭或正确配置避免重定向到内网地址
缓存控制
proxy_cache:
proxy_cache my_cache; proxy_cache_key "$scheme$request_method$host$request_uri"; proxy_cache_valid 200 302 10m;- 启用响应缓存,显著减轻后端负载
- 需要配合
proxy_cache_path指令使用
大文件处理
proxy_max_temp_file_size:
nginxproxy_max_temp_file_size 1024m;- 当响应体超出缓冲区时,允许使用的临时文件最大大小
- 0表示禁用临时文件
proxy_temp_file_write_size:
nginxproxy_temp_file_write_size 32k;- 写入临时文件时每次写入的数据量
负载均衡容错
proxy_next_upstream:
nginxproxy_next_upstream error timeout http_500 http_502 http_503 http_504;- 定义在什么情况下请求应转发到下一个服务器
- 生产建议:包含error、timeout和5xx状态码
proxy_next_upstream_tries:
nginxproxy_next_upstream_tries 3;- 尝试转发到下一个服务器的最大次数
健康检查机制
健康检查是生产环境中必不可少的配置,它能够自动屏蔽故障节点,确保系统的高可用性
被动健康检查
upstream backend {
server 192.168.1.101:8080 max_fails=3 fail_timeout=30s;
server 192.168.1.102:8080 max_fails=3 fail_timeout=30s;
}max_fails:在fail_timeout时间内失败达到此次数,标记服务器不可用fail_timeout:既是失败计数的时间窗口,也是服务器被标记为不可用的持续时间
工作原理:
- 当请求失败(连接超时或返回5xx错误),失败计数器+1
- 在
fail_timeout时间窗口内累计失败达到max_fails,标记服务器不可用 - 经过
fail_timeout时间后,Nginx会尝试恢复该服务器
主动健康检查
需Nginx Plus或第三方模块
upstream backend {
zone backend 64k;
server 192.168.1.101:8080;
server 192.168.1.102:8080;
health_check interval=5s fails=3 passes=2 uri=/health;
}- 定期发送探测请求验证服务器状态
- 更及时地发现故障节点
负载均衡优化
会话保持方案
Cookie绑定
upstream backend {
sticky cookie srv_id expires=1h domain=.example.com path=/;
server 192.168.1.101:8080;
server 192.168.1.102:8080;
}- 通过注入Cookie实现会话保持
- 比IP哈希更适用于客户端使用NAT的环境
SSL/TLS
server {
listen 443 ssl;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
location / {
proxy_pass http://backend;
proxy_set_header X-Forwarded-Proto https;
}
}- 前端HTTPS,后端HTTP
- 通过
X-Forwarded-Proto头告知后端原始协议
连接池配置
upstream backend {
server 192.168.1.101:8080;
server 192.168.1.102:8080;
keepalive 32; # 保持的长连接数量
}
server {
location / {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
}
}- 减少TCP连接建立的开销
- 提高高并发下的性能
