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;  
    }
  • 注意:
  1. 使用IP_Hash需要Nginx是最前端的服务器,否则无法获取到正确的客户端IP。
  2. 如果在IP_Hash的Nginx服务器之后还有其他的负载均衡,那么具体请求落在某一台服务器就无法确定了。

least_conn

  • 概述: 最小连接算法,它会选择后台服务器中积压的连接数最少的服务器来处理当前请求。
  • 算法简介:
    nginx内部会记录每个后台服务器当前的连接数和权重,使用最小连接算法时,会选出后台服务器中连接数/权重最小的服务器处理请求。

第三方策略

  • fair: 按照服务端响应时间来分配请求,响应时间最短的优先分配。
  • url_hash: 根据URL的hash结果来分配请求,它会使每个URL定向到同一个后端服务器中