Nginx负载均衡详解
- Nginx的负载均衡策略
- 轮询
- 权重weight
- ip_hash
- least_conn
- 第三方策略
接上一篇的入门,本篇主要介绍Nginx的负载均衡策略
Nginx的负载均衡策略
轮询
- 描述: 所有请求按照时间顺序地轮流分配到应用服务器上,它可以均衡的将负载分散在后端服务器上,但是并不关心后端服务器的连接数和系统负载,它是
默认
的负载均衡策略。在轮序中如果服务器宕机了会自动移除服务器。一般用于后端服务器性能均等的情况下。 - 参数:
参数名 | 用途 |
fail_timeout | 设置的时间内服务器没有响应则认为服务器失效,默认10s |
max_fails | 允许连接失败的次数,默认1 |
fail_time | 服务器被移除轮询队列的时间,默认10s(在移除的时间内不再被轮询请求) |
backup | 标记该服务器为备用服务器,当主服务器宕机时,它将会代替主服务器接收请求 |
down | 标记此服务器永久停机 |
- 配置范例:
upstream xx.com{
server 192.168.12.100:5000 fail_timeout=2s max_fails=1;
server 192.168.12.101:5000 fail_timeout=2s max_fails=1;
}
server {
listen 80;
server_name 192.168.12.101;
location / {
proxy_pass http://xx.com;
proxy_redirect default;
proxy_connect_timeout 2s;
}
.......省略
}
在上述配置中,如果一台服务器出现了宕机,那么等待的时间为:
time = proxy_connect_timeout + fail_timeout * max_fails = 2 + 2 * 1 = 4s
权重weight
- 概述: 在轮询算法的基础上指定轮询的概率。权重越高被分配的记录越大,适合服务器硬件配置有一定差距的情况
- 配置范例:
upstream xx.com{
server 192.168.12.100:5000 weight=1;
server 192.168.12.101:5000 weight=1;
server 192.168.12.101:5000 weight=3;
}
如上图中的配置,权重为1和3,那么权重为3的服务器被轮询的几率为1的3倍。
- 加权轮询算法
- 概述: 加权轮询算法看似简单,例如上述的配置中,有10个请求,假设权重为1的服务器为a,b,权重为3的服务器为c。他们分配的顺序可能为:a,a,b,b,c,c,c,c,c,c。那么对b服务器将会有连续的多个请求,分布并不均匀,容器造成负载突然上升。
所以在Nginx中目前使用的是平滑的加权轮询,它会将请求分散开不再是多个连续的,例如:c,a,b,c,c,a,c,b,c,c。 - 算法介绍:
首先介绍算法中的几个参数
- weight: 配置文件中配置的weight值。
- effective_weight: 服务器的有效权重,初始值为weight,Nginx如果发现与后端的请求中出现超时或者错误将会减少有效权重的值,降低以后再接收请求如果正常则会逐渐增加,直到等于weight。这个参数主要是为了在出现错误时降低权重值。
- current_weight: 服务器的当前权重,初始值为0,并且在每次轮询选取服务器时会动态的调整。
每次选取时会先遍历后端服务器,并对每个服务器的权重执行运算,current_weight = current_weight + effective_weight。(当前权重 + 有效权重)同时设定Total的值为当前所有服务器的effective_weight和
每次选定了current_weight值最大的服务器处理请求后,将此服务器的current_weight = current_weight - total。(当前权重 - 总权重),没有被选定的权重不变。
- 案例
现在假设,三台服务器a,b,c的权重分别为4,2,1。那么在7此的轮询中a会被选中4次、b会被选中2次、c会被选中1次,且分布平滑
。
为了方便计算,假设所有的服务器都良好可用,那么effective_weight = weight,total = weight1 + weight2 + weight3 = 7。
次数 | 选取时的权重值 | 选定结果 | 选定后的权重 |
1 | a=0+4=4,b=0+2=2,c=1 | a | a=4-7=-3,b=2,c=1 |
2 | a= -3+4=1,b=2+2=4,c=1+1=2 | b | a=1,b=4-7=-3,c=2 |
3 | 5,-1,3 | a | -2,-1,3 |
4 | 2,1,4 | c | 2 ,1,-3 |
5 | 6,3,-2 | a | -1,3,-2 |
6 | 3,5,-1 | b | 3,-2,-1 |
7 | 7,0,0 | a | 0,0,0 |
最终的顺序为a,b,a,c,a,b,a。符合预期。
ip_hash
- 概述: 通过对IP的Hash值进行计算然后选择分配的服务器。这个方法可以使客户端的请求发送到相同的服务器以保证session会话,并且可以使用权重。
- 算法简介: 看不懂C语言,只能大致了解了Hash算法是将IP的前三段进行计算的
for (i = 0; i < 3; i++) {
hash = (hash * 113 + iphp->addr[i]) % 6271; //iphp->addr[i]为ip的点分十进制法的第i段
}
根据计算出来的Hash值进行分配。
- 配置:
upstream xx.com{
ip_hash; #保证每个访客固定访问一个后端服务器
server localhost:8080 weight=2;
server localhost:8081;
server localhost:8082;
server localhost:8083 max_fails=3 fail_timeout=20s;
}
- 注意:
- 使用IP_Hash需要Nginx是最前端的服务器,否则无法获取到正确的客户端IP。
- 如果在IP_Hash的Nginx服务器之后还有其他的负载均衡,那么具体请求落在某一台服务器就无法确定了。
least_conn
- 概述: 最小连接算法,它会选择后台服务器中积压的连接数最少的服务器来处理当前请求。
- 算法简介:
nginx内部会记录每个后台服务器当前的连接数和权重,使用最小连接算法时,会选出后台服务器中连接数/权重最小
的服务器处理请求。
第三方策略
- fair: 按照服务端响应时间来分配请求,响应时间最短的优先分配。
- url_hash: 根据URL的hash结果来分配请求,它会使每个URL定向到同一个后端服务器中