负载均衡
# 负载均衡
# 快速上手
# 门户服务
http {
upstream load_balance_server {
# weigth参数表示权值,权值越高被分配到的几率越大
server 192.168.31.31:80 weight=5;
server 192.168.31.32:80 weight=1;
server 192.168.31.33:80 weight=6;
}
server {
listen 80;
location /api {
proxy_pass http://load_balance_server;
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 后台服务
本处用 3 台 nginx 模拟
在每个机器上面加入配置.
# 机器 192.168.31.31
location /api {
echo "192.168.31.31";
}
# 机器 192.168.31.32
location /api {
echo "192.168.31.32";
}
# 机器 192.168.31.33
location /api {
echo "192.168.31.33";
}
2
3
4
5
6
7
8
9
10
11
12
13
14
# 测试负载均衡
# unclezs @ mc in ~/apps/nginx [21:43:00]
$ curl 127.0.0.1/api
192.168.31.33
# unclezs @ mc in ~/apps/nginx [21:43:01]
$ curl 127.0.0.1/api
192.168.31.31
# unclezs @ mc in ~/apps/nginx [21:43:01]
$ curl 127.0.0.1/api
192.168.31.32
2
3
4
5
6
7
8
9
可以看到请求被分摊到了 3 个机器。
# 负载均衡策略
Nginx 提供了多种负载均衡策略,让我们来一一了解一下:
# 轮询
默认权重为 1
upstream load_balance_server {
server 192.168.31.31:80;
server 192.168.31.32:80;
server 192.168.31.33:80;
}
2
3
4
5
# 加权轮询
weigth参数表示权值,权值越高被分配到的几率越大
upstream load_balance_server {
server 192.168.31.31:80 weight=5;
server 192.168.31.32:80 weight=1;
server 192.168.31.33:80 weight=6;
}
2
3
4
5
# 最少连接
upstream load_balance_server {
least_conn;
server 192.168.31.31:80;
server 192.168.31.32:80;
server 192.168.31.33:80;
}
2
3
4
5
6
# 加权最少连接
upstream load_balance_server {
least_conn;
server 192.168.31.31:80 weight=5;
server 192.168.31.32:80 weight=1;
server 192.168.31.33:80 weight=2;
}
2
3
4
5
6
# IP Hash
请求发送到的服务器由客户端 IP 地址确定。在这种情况下,使用 IPv4 地址的前三个八位字节或整个 IPv6 地址来计算哈希值。该方法保证来自同一地址的请求到达同一服务器,除非它不可用。
upstream load_balance_server {
ip_hash;
server 192.168.31.31:80 weight=5;
server 192.168.31.32:80 weight=1;
server 192.168.31.33:80 weight=2;
}
2
3
4
5
6
如果需要暂时从负载平衡轮换中删除其中一台服务器,可以使用down (opens new window)参数对其进行标记,以保留客户端 IP 地址的当前散列。本服务器处理的请求会自动发送到组中的下一个服务器:
upstream load_balance_server {
ip_hash;
server 192.168.31.31:80 weight=5;
server 192.168.31.32:80 weight=1;
server 192.168.31.33:80 down;
}
2
3
4
5
6
# 通用 Hash
通用哈希 (opens new window)– 请求发送到的服务器由用户定义的键确定,该键可以是文本字符串、变量或组合。例如,密钥可能是配对的源 IP 地址和端口,或者是本例中的 URI:
upstream load_balance_server {
hash $request_uri;
server 192.168.31.31:80 weight=5;
server 192.168.31.32:80 weight=1;
server 192.168.31.33:80 weight=2;
}
2
3
4
5
6
该指令的可选一致参数hash
启用ketama (opens new window)一致哈希负载平衡。请求根据用户定义的散列键值均匀分布在所有上游服务器上。如果将上游服务器添加到上游组或从上游组中删除,则仅重新映射少数键,从而在负载平衡缓存服务器或其他累积状态的应用程序的情况下最大限度地减少缓存未命中。
# 最少时间
仅限 NGINX Plus,对于每个请求,NGINX Plus 选择具有最低平均延迟和最少活动连接数的服务器,其中最低平均延迟是根据指令中包含的以下参数计算得出的: (opens new window)least_time
header
– 从服务器接收第一个字节的时间last_byte
– 从服务器接收完整响应的时间last_byte inflight
– 考虑到不完整的请求,从服务器接收完整响应的时间
upstream load_balance_server {
least_time header;
server 192.168.31.31:80;
server 192.168.31.32:80;
server 192.168.31.33:80;
}
2
3
4
5
6
# 随机
每个请求将被传递到随机选择的服务器。如果two
指定了参数,首先 NGINX 会根据服务器权重随机选择两台服务器,然后使用指定的方法选择其中一台服务器:
least_conn
– 最少的活动连接数least_time=header
(NGINX Plus) – 从服务器接收响应头的最短平均时间 ($upstream_header_time
(opens new window))least_time=last_byte
(NGINX Plus) – 从服务器接收完整响应的最短平均时间 ($upstream_response_time
(opens new window))
upstream load_balance_server {
random two least_time=last_byte;
server 192.168.31.31:80;
server 192.168.31.32:80;
server 192.168.31.33:80;
}
2
3
4
5
6
随机负载平衡方法应用于多个负载平衡器将请求传递到同一组后端的分布式环境。对于负载均衡器可以全面了解所有请求的环境,请使用其他负载均衡方法,例如循环、最少连接和最少时间。
# 服务器慢启动
服务器慢启动功能可防止最近恢复的服务器被连接淹没,这可能会超时并导致服务器再次被标记为失败。
在 NGINX Plus 中,慢启动允许上游服务器0
在恢复或可用后逐渐将其权重从其标称值恢复。这可以通过指令的slow_start
(opens new window)参数来完成server
:
upstream backend {
server backend1.example.com slow_start=30s;
server backend2.example.com;
server 192.0.0.1 backup;
}
2
3
4
5
时间值(此处为30
秒)设置 NGINX Plus 将与服务器的连接数增加到完整值的时间。
请注意,如果组中只有一个服务器,则该指令的max_fails
(opens new window)、fail_timeout
(opens new window)和slow_start
(opens new window)参数将server
被忽略,并且该服务器永远不会被视为不可用。
# 会话持久性
会话持久性意味着 NGINX Plus 识别用户会话并将给定会话中的所有请求路由到同一上游服务器。
NGINX Plus 支持三种会话持久化方法。这些方法是使用sticky
(opens new window)指令设置的。(对于 NGINX Open Source 的会话持久性,请使用上述的hash
指令ip_hash
。)
# 粘性 cookie
粘性 cookie (opens new window) – NGINX Plus 将会话 cookie 添加到来自上游组的第一个响应中,并标识发送响应的服务器。客户端的下一个请求包含 cookie 值,NGINX Plus 将请求路由到响应第一个请求的上游服务器:
upstream backend {
server backend1.example.com;
server backend2.example.com;
sticky cookie srv_id expires=1h domain=.example.com path=/;
}
2
3
4
5
在示例中,srv_id
参数设置 cookie 的名称。可选expires
参数设置浏览器保留 cookie 的时间(此处为1
小时)。可选domain
参数定义为其设置 cookie 的域,可选path
参数定义为其设置 cookie 的路径。这是最简单的会话持久化方法。
# 粘性路由
粘性路由 (opens new window)——NGINX Plus 在收到第一个请求时为客户端分配一个“路由”。所有后续请求都与指令的route
(opens new window)参数进行比较,server
以识别请求代理到的服务器。路由信息取自 cookie 或请求 URI。
upstream backend {
server backend1.example.com route=a;
server backend2.example.com route=b;
sticky route $route_cookie $route_uri;
}
2
3
4
5
# 粘性学习
粘性学习 (opens new window)方法——NGINX Plus 首先通过检查请求和响应来找到会话标识符。然后 NGINX Plus “学习” 哪个上游服务器对应哪个会话标识符。通常,这些标识符在 HTTP cookie 中传递。如果请求包含已经“学习”的会话标识符,NGINX Plus 会将请求转发到相应的服务器:
upstream backend {
server backend1.example.com;
server backend2.example.com;
sticky learn
create=$upstream_cookie_examplecookie
lookup=$cookie_examplecookie
zone=client_sessions:1m
timeout=1h;
}
2
3
4
5
6
7
8
9
EXAMPLECOOKIE
在示例中,上游服务器之一通过在响应中设置 cookie 来创建会话。
create
参数指定一个变量,该变量指示如何创建新会话。在示例中,新会话是从EXAMPLECOOKIE
上游服务器发送的 cookie 创建的。lookup
参数指定如何搜索现有会话。EXAMPLECOOKIE
在我们的示例中,在客户端发送的 cookie 中搜索现有会话。zone
参数指定一个共享内存区域,其中保存有关粘性会话的所有信息。在我们的示例中,该区域名为client_sessions,大小为1
兆字节。
这是一种比前两种更复杂的会话持久性方法,因为它不需要在客户端保留任何 cookie:所有信息都保存在服务器端的共享内存区域中。
如果集群中有多个 NGINX 实例使用“粘性学习”方法,则可以在以下条件下同步它们共享内存区域的内容:
- 这些区域具有相同的名称
- 该
zone_sync
(opens new window)功能在每个实例上配置 - 指定
sync
参数
sticky learn
create=$upstream_cookie_examplecookie
lookup=$cookie_examplecookie
zone=client_sessions:1m
timeout=1h
sync;
}
2
3
4
5
6
7
有关详细信息,请参阅集群中的运行时状态共享 (opens new window)。
# 健康检查
# 被动健康检查
对于被动健康检查,NGINX 在事务发生时监控它们,并尝试恢复失败的连接。如果事务仍然无法恢复,NGINX 将服务器标记为不可用并暂时停止向它发送请求,直到它再次被标记为活动状态。
上游服务器被标记为不可用的条件是为每个上游服务器定义的,并带有块中server
(opens new window)指令的参数upstream
:
- fail_timeout (opens new window) – 设置必须发生多次失败尝试才能将服务器标记为不可用的时间,以及将服务器标记为不可用的时间(默认为 10 秒)。
- max_fails (opens new window)– 设置在将服务器标记为不可用期间 必须发生的失败尝试次数(默认为 1 次尝试)。
upstream backend {
server backend1.example.com;
server backend2.example.com max_fails=3 fail_timeout=30s;
}
2
3
4
# 主动健康检查
可以通过向每个服务器发送特殊的健康检查请求并验证正确的响应来定期检查上游服务器的健康状况。
要启用主动健康检查:
1、在location
(opens new window)将请求 ( proxy_pass
(opens new window)) 传递给上游组的 中,包括health_check
(opens new window)指令:
server {
location / {
proxy_pass http://backend;
health_check;
}
}
2
3
4
5
6
此代码段定义了一个服务器,它将所有请求 ( location /
) 传递给名为 的上游组backend
。它还使用health_check
(opens new window)指令启用高级健康监控:默认情况下,NGINX 每五秒向组中的每个服务器发送一个“ /backend
”请求。如果发生任何通信错误或超时(服务器以超出范围的状态代码进行响应200
)399
,则运行状况检查将失败。服务器被标记为不健康,NGINX 不会向它发送客户端请求,直到它再次通过健康检查。
您可以选择指定另一个端口进行健康检查,例如,用于监控同一主机上许多服务的健康状况。port
(opens new window)使用指令的参数指定一个新端口health_check
(opens new window):
server {
location / {
proxy_pass http://backend;
health_check port=8080;
}
}
2
3
4
5
6
2、在上游服务器组中,使用以下zone
(opens new window)指令定义共享内存区域:
http {
upstream backend {
zone backend 64k;
server backend1.example.com;
server backend2.example.com;
server backend3.example.com;
server backend4.example.com;
}
}
2
3
4
5
6
7
8
9
该区域在所有工作进程之间共享,并存储上游组的配置。这使工作进程能够使用同一组计数器来跟踪来自组中服务器的响应。
可以使用health_check
指令的参数覆盖主动健康检查的默认值:
location / {
proxy_pass http://backend;
health_check interval=10 fails=3 passes=2;
}
2
3
4
在这里,
- interval (opens new window)参数将运行状况检查之间的延迟从默认的 5 秒增加到 10 秒。
- fails (opens new window)参数要求服务器未通过三项健康检查才能将其标记为不健康(高于默认值)。
- passes (opens new window)参数意味着服务器必须通过两次连续检查才能再次标记为健康,而不是默认一次。
您还可以使用keepalive_time
(opens new window)参数启用连接缓存 - 在 TLS 上游的情况下,每次运行状况检查探测都不会发生完整的 TLS 握手,并且可以在指定的时间段内重用连接:
location / {
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_pass https://backend;
health_check interval=1 keepalive_time=60s;
}
2
3
4
5
6
# 其他一些
也属于主动健康检查,nginx 还支持 自定义 url、自定义匹配规则、强制检查等,可自行了解。