概述
本章,您将学习到负载均衡中的负载规则(负载策略、负载算法)。
在 代理服务 文章中提到了负载规则,其主要目的是根据业务场景的不同来分发流量,实现流量的均衡分布。在社区版 Nginx 中,可用的基础负载规则有:
- 轮询(Round Robin)- 若不指定任何规则,则默认使用该规则
- 加权轮询(Weighted Round Robin)
- 最小连接(Least Connections)
- IP 哈希(IP Hash)
- 随机(Random)
上游服务器(Upstream Server):指一组后端服务器。当代理服务器拦截到客户端请求后,就会根据负载规则将这些请求转发给这些后端服务器。需要注意的是,在标准的生产环境中,后端服务器的数量通常建议大于等于 3 台(当然这不是强制的,1 台 或 2 台都是被允许的),以保证足够的性能、冗余以及可用性。在主配置文件 nginx.conf 中可通过
upstream 上下文来定义一组后端服务器,需要注意 upstream 上下文只能配置在 http 上下文中。
社区版可用的负载策略
轮询
轮询是分发请求的默认规则,每个请求会按照先后顺序分配到不同的后端服务器上。在硬件同构的生产环境中,轮询是最高效、最稳健且资源消耗最低的负载均衡规则。
例如:
...
events {
...
}
http {
...
# 定义了名为 backend1 的一组后端服务器(未指定任何负载策略,默认使用轮询)
upstream backend1 {
server 192.168.100.30;
server 192.168.100.35;
server 192.168.100.40;
}
...
server {
...
location / {
...
}
}
}
第一个请求会被 192.168.100.30 后端服务器进行处理,第二个请求会被 192.168.100.35 后端服务器进行处理,第三个请求会被 192.168.100.40 后端服务器进行处理,如此往复循环。
在生产环境下,前面的配置搭配几个关键参数还可提升健壮性:
...
events {
...
}
http {
...
# 定义了名为 backend1 的一组后端服务器(未指定任何负载策略,默认使用轮询)
upstream backend1 {
server 192.168.100.30 max_fails=3 fail_timeout=60s;
server 192.168.100.35 max_fails=3 fail_timeout=60s;
server 192.168.100.40 max_fails=3 fail_timeout=60s;
}
...
server {
...
location / {
...
}
}
}
参数说明:
max_fails=3- 在fail_timeout参数指定的时间内与后端服务器的通信次数上限,当到达上限次数后,将认为对应的后端服务器处于临时不可用状态且不可用的时间同样由fail_timeout参数决定fail_timeout=40s- 在指定的时间内与后端服务器进行通信的次数上限;后端服务器临时不可用的时间
根据 max_fails 和 fail_time 参数设置的不同,您还应该调整与连接相关的指令参数,即:
proxy_connect_timeoutproxy_send_timeoutproxy_read_timeoutproxy_next_upstream
比如配置 max_fails=3 和 fail_timeout=60s,则:
proxy_connect_timeout 5s;
proxy_read_timeout 10s;
proxy_send_timeout 10s;
proxy_next_upstream error timeout http_502 http_504;
keepalive 32 local;加权轮询
所谓加权轮询,即在轮询的基础之上添加权重参数,适合后端服务器性能不统一的情况(即所谓的硬件异构环境)。权重数字越高,分配的请求量越大。比如后端服务器 A(192.168.100.30)性能最高,配置的权重参数为 4;后端服务器 B(192.168.100.35) 性能次之,配置的权重参数为 2;后端服务器 C (192.168.100.40)性能最差,配置的权重参数为 1。在一个完整的时间范围内,后端服务器 A 会拿到 4 倍于后端服务器 C 的请求量。
在一个完整的时间周期范围内(比如 1 星期),理论上分配的请求量如下表所示:
| 服务器 IP 地址 | 权重 | 请求占比计算 | 理论上分配请求流量的比例 |
|---|---|---|---|
| 192.168.100.30 | 4 | 4/7 | 约 57.1% |
| 192.168.100.35 | 2 | 2/7 | 约 28.6% |
| 192.168.100.40 | 1 | 1/7 | 约 14.3% |
配置示例如下所示:
...
events {
...
}
http {
...
# 定义了名为 backend1 的一组后端服务器
upstream backend1 {
# 性能最高,权重设为 4
server 192.168.100.30 weight=4 max_fails=3 fail_timeout=60s;
# 性能次之,权重设为 2
server 192.168.100.35 weight=2 max_fails=3 fail_timeout=60s;
# 性能最差,权重设为 1
server 192.168.100.40 weight=1 max_fails=3 fail_timeout=60s;
}
...
server {
...
location / {
...
}
}
}
当需要上线新的后端服务器节点或旧后端服务器节点从故障中恢复时,如果还按照原始的配置分配流量,可能会遭遇流量洪峰的冲击导致实际的业务响应缓慢或崩溃,为了防止这种情况,您还可以根据后端服务器性能的不同差异化配置 slow_start 参数,如:
...
events {
...
}
http {
...
# 定义了名为 backend1 的一组后端服务器
upstream backend1 {
# 性能最高,权重设为 4,配置慢启动的时间应该最长
server 192.168.100.30 weight=4 max_fails=3 fail_timeout=60s slow_start=30s;
# 性能次之,权重设为 2
server 192.168.100.35 weight=2 max_fails=3 fail_timeout=60s slow_start=20s;
# 性能最差,权重设为 1,配置慢启动的时间应该最短
server 192.168.100.40 weight=1 max_fails=3 fail_timeout=60s slow_start=10s;
}
...
server {
...
location / {
...
}
}
}
参数说明:
slow_start=30s- 慢启动时间,即表示在 30 秒内,该后端服务器的权重从 0 逐渐增加到设定值 4,防止流量洪峰的情况出现。需要注意该参数不能与 IP 哈希(IP Hash)、随机(Random)负载策略一起使用。
IP 哈希
IP 哈希:一种基于客户端 IP 地址(IPv4 和 IPv6 都支持)的负载策略,即通过判断客户端的 IP 地址来决定将请求分发给哪个后端服务器。具体原理:
- IPv4 - 取 IPv4 地址的前 24 bit 做为哈希键参与运算
- IPv6 - 将整个 128 bit 作为哈希键参与运算
配置示例如下:
...
events {
...
}
http {
...
# 定义了名为 backend1 的一组后端服务器
upstream backend1 {
ip_hash;
server 192.168.100.30 max_fails=3 fail_timeout=60s;
server 192.168.100.35 max_fails=3 fail_timeout=60s;
server 192.168.100.40 max_fails=3 fail_timeout=60s;
}
...
server {
...
location / {
...
}
}
}
指令说明:
ip_hash指令 - 启用 IP 哈希负载规则,只能配置在 upstream 上下文中
最少连接
最少连接:一种负载策略,其核心思想是将新请求分发给当前活跃 TCP 连接数(即已建立但尚未完成响应的连接)最少的后端服务器上。这种负载策略可以有效平衡后端服务器的负载情况:
- 避免一个或多个后端服务器因请求过多处于过载状态
- 避免一个或多个后端服务器因请求过少处于空闲状态
启用该负载策略后,可有效提升后端服务器整体的资源利用率与请求效率。
配置示例如下:
...
events {
...
}
http {
...
# 定义了名为 backend1 的一组后端服务器
upstream backend1 {
least_conn;
server 192.168.100.30 max_fails=3 fail_timeout=60s;
server 192.168.100.35 max_fails=3 fail_timeout=60s;
server 192.168.100.40 max_fails=3 fail_timeout=60s;
}
...
server {
...
location / {
...
}
}
}
指令说明:
least_conn指令 - 启用最少连接负载策略
假设:
- 192.168.100.30 当前有 10 个活跃 TCP 连接
- 192.168.100.35 当前有 5 个活跃 TCP 连接数
- 192.168.100.40 当前有 8 个活跃 TCP 连接数
当有新的客户端请求到达 Nginx 代理服务器时,该请求会分发给 192.168.100.35 这台后端服务器上。
随机
随机:一种负载策略,其通过特有的随机函数使请求均匀分发在不同的后端服务器上,特别适用于硬件同构的生产环境中。只要请求的数量样本足够多,从统计概率上来说就是均匀分发请求。需要注意的是,早期的一些中文资料或文档提到 Nginx 社区版原生不支持这种负载策略,这是不正确的。
Nginx 社区版的相关指令:
-
使用
random指令,语法为random [two [method]];two参数 - 指随机选择两台后端服务器method参数 - 替换为具体的负载策略,社区版只能默认为least_conn。least_time为 Nginx 商业版(Nginx Plus)的专属功能
以下的配置都可以被接受:
random;- 不书写参数,则随机选择一台后端服务器。若后端服务器配置了权重参数(weight=Number),则选择一台后端服务器的概率会等于权重比例random two;或random two least_conn;- 随机选择两台服务器,然后根据默认的least_conn负载策略进一步选择其中一台后端服务器来处理请求
配置示例一:
...
events {
...
}
http {
...
# 定义了名为 backend1 的一组后端服务器
upstream backend1 {
# 启用随机负载策略
random;
server 192.168.100.30 weight=4 max_fails=3 fail_timeout=60s; # 4/7 的概率被选择
server 192.168.100.35 weight=2 max_fails=3 fail_timeout=60s; # 2/7 的概率被选择
server 192.168.100.40 weight=1 max_fails=3 fail_timeout=60s; # 1/7 的概率被选择
}
...
server {
...
location / {
...
}
}
}
配置示例二:
...
events {
...
}
http {
...
# 定义了名为 backend1 的一组后端服务器
upstream backend1 {
# 启用随机负载策略
random two least_conn;
server 192.168.100.30 max_fails=3 fail_timeout=60s;
server 192.168.100.35 max_fails=3 fail_timeout=60s;
server 192.168.100.40 max_fails=3 fail_timeout=60s;
}
...
server {
...
location / {
...
}
}
}










