负载均衡是指将来自客户端的请求分发到多个后端服务器上,以达到提高系统性能、增加可用性和实现水平扩展的目的。上篇文章讲反向代理的时候已经知道使用proxy_pass指令将客户端请求转发到一个后端服务器,这里转到多个服务器也就是实现负载均衡需要结合upstream命令。
upstream 指令语法:
upstream name { 后端服务列表... }
首先定义一个upstream的名称,这个名称会在proxy_pass指定URL时候使用。upstream块内部定义被负载的后端服务器列表。
如下例子:
server {
listen 8081;
location / {
root html/8081;
}
}
server {
listen 8082;
location / {
root html/8082;
}
}
server {
listen 8083;
location / {
root html/8083;
}
}
upstream backend {
server localhost:8081;
server localhost:8082;
server localhost:8083;
}
server {
listen 8080;
location / {
proxy_pass http://backend;
}
}
这里为了演示多个后台服务,nginx起了8081,8082,8083三个server最为后端被负载的服务,通过upstream指定这三个端口服务为候选的负载服务列表,服务名为backend。然后8080的访问都负载到backend服务上。
这样当访问 http://localhost:8080的时候会负载到后面三个服务上。
负载均衡策略
负载的服务有多台,那么当本次请求到nginx后,怎样选择后台的具体哪一台服务呢。这里有以下几种策略:
-
轮询(Round Robin): 将请求依次分配给后端服务器列表中的每个服务器,按照顺序循环。这是一种简单且公平的负载均衡策略,适用于后端服务器性能相近且负载均衡需求不高的情况。默认情况下使用该种策略。
-
加权轮询(Weighted Round Robin): 类似于轮询,但可以为每个后端服务器分配不同的权重,以反映它们的处理能力或负载情况。具有更高权重的服务器将获得更多的请求,适用于后端服务器性能不均衡或不同负载情况的场景。
upstream backend { server localhost:8081 weight=3; server localhost:8082 weight=2; server localhost:8083 weight=1; }
使用weight指定每台服务器的权重值。weight默认值是1。
upstream中的server指令除了添加weight参数外,还可以指定以下几个参数:
weight
=number
:指定同时最大活跃连接数,默认0不限制max_fails
=number
:定义后端服务器允许的最大连续失败次数,当达到该值时,当前server被标记为不可用。默认值是1fail_timeout
=time
:定义服务器被标记为不可用的时间,也即服务器被标记为不可用后的冷却时间,可以是秒(s)、毫秒(ms)、分(m)等时间单位。默认值是10s,要结合max_fails使用backup:将服务器标记为备用服务器,在主服务器不可用时才会被使用
down:将服务器标记为永久不可用,也就是下线
slow_start
=time:slow_start 参数允许您指定一个时间段,在这个时间段内,新添加的服务器将逐渐增加其权重,直到达到配置的权重值。这样做可以确保新服务器在开始处理正常负载之前不会立即接收到太多的请求,从而有效地平衡负载并提高系统的稳定性。如下例子:
upstream test { server test1.example.com weight=5; server test2.example.com max_conns=10; server 192.168.1.100:8080 max_fails=2 fail_timeout=30s; server backup.example.com backup; }
test1.example.com 的权重为 5,意味着它将获得更多的请求。
test22.example.com 的最大并发数限制为 10。
192.168.1.100:8080 在两次尝试连接失败后,将被标记为不可用,直到 30 秒后才重新尝试连接。
backup.example.com 被定义为备份服务器,只有当其他服务器不可用时才会被使用。
-
IP 哈希(IP Hash): 根据客户端的 IP 地址将请求分发到后端服务器。相同 IP 的请求始终被发送到相同的后端服务器上,适用于需要保持会话一致性或缓存的场景。
upstream backend { ip_hash; ... }
IP哈希配置非常简单,在upstream块配置上ip_hash指令即可。
-
最小连接数(Least Connections): 将请求发送到当前连接数最少的后端服务器上,以确保负载更加均衡。适用于后端服务器响应时间不均衡或处理请求时间不确定的情况。
upstream backend { least_conn; ... }
-
最快响应时间(Least Time): 将请求发送到响应时间最短的后端服务器上,以确保用户获得最佳的响应速度。通常需要监控后端服务器的响应时间,并动态调整负载均衡策略。
upstream backend { least_time first_byte; ... }
这里least_time指定计算响应时间的结束时间,有几个可选值:
header:表示返回响应头时间作为结束时间
last_byte:表示整个响应报文响应完成作为结束时间
另外还可以指定inflight参数,未完成的请求也参与统计种。
-
随机(Random): 随机选择一个后端服务器来处理请求。这种策略简单且易于实现,但可能导致不均衡的负载分布。
upstream backend { random; ... }
-
哈希(Hash): 指定一个hash key进行分发。key值可以是请求上下文的变量,可以是文本内容等。相同 hash值 的请求将始终被发送到相同的后端服务器上。这里要注意服务器的数量增加或减少会进行rehash,可能会是原来的分发结果不一致。
upstream backend { hash $request_uri; ... }
如上根据请求的url进行hash后分发。