nginx负载均衡中常见的算法及原理

Posted 一夜入秋

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了nginx负载均衡中常见的算法及原理相关的知识,希望对你有一定的参考价值。

nginx负载均衡中常见的算法及原理

Nginx 可以基于ngx_http_upstream_module模块
提供服务器分组转发、权重分配、状态监测、调度算法等高级功能。

http upstream配置参数

#自定义一组服务器,配置在http块内
upstream name  
 server .....
 ......

示例:
upstream backend 
    server backend1.example.com       weight=5;
    server backend2.example.com:8080;
    server unix:/tmp/backend3;

    server backup1.example.com:8080   backup;
    server backup2.example.com:8080   backup;


server 
    location / 
        proxy_pass http://backend;
    


server address [parameters];
#配置一个后端web服务器,配置在upstream内,至少要有一个server服务器配置。
定义服务器的address和其他parameters。该地址可以指定为域名或IP地址,可以带端口。如果未指定端口,则默认使用80端口。

#server支持的parameters如下:
weight=number #设置权重,默认为1,实现类似于LVS中的WRR,WLC等
max_conns=number  #给当前后端server设置最大活动链接数,默认为0表示没有限制
max_fails=number  #后端服务器的下线条件,当客户端访问时,对本次调度选中的后端服务器连续进行检测多少次,如果都失败就标记为不可用,默认为1次,当客户端访问时,才会利用TCP触发对探测后端服务器健康性检查,而非周期性的探测
fail_timeout=time #后端服务器的上线条件,对已经检测到处于不可用的后端服务器,每隔此时间间隔再次进行检测是否恢复可用,如果发现可用,则将后端服务器参与调度,默认为10秒
backup  #设置为备份服务器,当所有后端服务器不可用时,才会启用此备用服务器
down    #标记为down状态,可以平滑下线后端服务器
resolve #当server定义的是主机名的时候,当A记录发生变化会自动应用新IP而不用重启Nginx

hash KEY [consistent];
#基于指定请求报文中首部字段或者URI等key做hash计算,使用consistent参数,将使用ketama一致性hash算法,适用于后端是Cache服务器(如varnish)时使用,consistent定义使用一致性hash运算,一致性hash基于取模运算

hash $request_uri consistent; #基于用户请求的uri做hash
hash $cookie_sessionid  #基于cookie中的sessionid这个key进行hash调度,实现会话绑定

ip_hash;
#源地址hash调度方法,基于的客户端的remote_addr(源地址IPv4的前24位或整个IPv6地址)做hash计算,以实现会话保持

least_conn;
#最少连接调度算法,优先将客户端请求调度到当前连接最少的后端服务器,相当于LVS中的WLC

Nginx 负载均衡中常见的算法

这里的示例环境是:

client:10.0.0.8
Nginx:10.0.0.100
nginx1:10.0.0.7
nginx2:10.0.0.17

轮询(round robin)

轮询算法是nginx的默认调度算法,是按照客户端的请求顺序来逐一的分配到不同的后端节点服务器上,这个与lvs的轮询是差不多的;假设后端的某个节点服务器宕机是,宕机的服务器会被自动从节点服务器池中删除,为了使客户端的用户访问不受影响,新的请求会分配给正常的服务器。
示例:

root@Nginx:~# vim /apps/nginx/conf/nginx.conf
#在http块中加上下面语句
upstream websrvs 
    server 10.0.0.7:80;
    server 10.0.0.17:80;

root@Nginx:~# vim /apps/nginx/conf.d/pc.conf 
server 
    listen 80;
    server_name www.zhanggui.com;
    location / 
        root /data/nginx/html/pc;
        index index.html index.htm;
        proxy_pass http://websrvs;                                                                   
    

#检查语法并重新加载配置文件
root@Nginx:~# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
root@Nginx:~# nginx -s reload
#客户端上测试验证数据
[root@client ~]#curl http://www.zhanggui.com
10.0.0.7
[root@client ~]#curl http://www.zhanggui.com
10.0.0.17
[root@client ~]#curl http://www.zhanggui.com
10.0.0.7
[root@client ~]#curl http://www.zhanggui.com
10.0.0.17
#lvs中没有健康检查,而nginx自带健康检查,假设后端一个服务器挂了,现在测试访问看一下
[root@nginx1 ~]# hostname -I
10.0.0.7
[root@nginx1 ~]# systemctl stop nginx
[root@client ~]#curl http://www.zhanggui.com
10.0.0.17
[root@client ~]#curl http://www.zhanggui.com
10.0.0.17
[root@client ~]#curl http://www.zhanggui.com
10.0.0.17
[root@client ~]#curl http://www.zhanggui.com
10.0.0.17

加权轮询(weight round robin)

这个是在轮询算法的基础上加了权重,这个也叫权重轮询算法;权重越高,被访问的几率就越大,这个是根据服务器的配置和性能来指定权重值的大小,要达到合理有效的地利用主机的资源。
示例:

root@Nginx:~# vim /apps/nginx/conf/nginx.conf
#在http块中加上下面语句
upstream websrvs 
    server 10.0.0.7:80 weight=2;
    server 10.0.0.17:80;

root@Nginx:~# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
root@Nginx:~# nginx -s reload
#在客户端上测试验证
[root@client ~]#curl http://www.zhanggui.com
10.0.0.17
[root@client ~]#curl http://www.zhanggui.com
10.0.0.7
[root@client ~]#curl http://www.zhanggui.com
10.0.0.7
[root@client ~]#curl http://www.zhanggui.com
10.0.0.17

源地址hash(ip_hash)

源地址hash调度方法,基于的客户端的remote_addr(源地址IPv4的前24位或整个IPv6地址)做hash计算,以实现会话保持;这个方法可以让同一用户的请求始终传递给同一服务器。除非该服务器出问题了,在服务器出问题后,客户端会重新将新的请求发往另外一台服务器。
注意:当负载均衡的算法为ip_hash时,后端服务器在负载均衡调度中的状态不能有weight和backup。
示例:

root@Nginx:~# vim /apps/nginx/conf/nginx.conf
#在http块中加上下面语句
upstream websrvs 
    ip_hash;
    server 10.0.0.7:80;
    server 10.0.0.17:80;

root@Nginx:~# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
root@Nginx:~# nginx -s reload
#在客户端上测试数据
[root@client ~]#curl http://www.zhanggui.com
10.0.0.17
[root@client ~]#curl http://www.zhanggui.com
10.0.0.17
[root@client ~]#curl http://www.zhanggui.com
10.0.0.17
[root@client ~]#curl http://www.zhanggui.com
10.0.0.17
#修改一下server 10.0.0.17:80 down;在测试访问查看
[root@client ~]#curl http://www.zhanggui.com
10.0.0.7
[root@client ~]#curl http://www.zhanggui.com
10.0.0.7
[root@client ~]#curl http://www.zhanggui.com
10.0.0.7
[root@client ~]#curl http://www.zhanggui.com
10.0.0.7

目的Url hash(url_hash)

url_hash这个算法是根据请求的url的hash值来调度到后端的服务器,当后端服务器为缓存时,效率会较高。
示例:

root@Nginx:~# vim /apps/nginx/conf/nginx.conf
#在http块中加上下面语句
upstream websrvs 
    hash $remote_addr;
    server 10.0.0.7:80;
    server 10.0.0.17:80;

root@Nginx:~# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
root@Nginx:~# nginx -s reload
#在客户端上测试数据
[root@client ~]#curl http://www.zhanggui.com
10.0.0.7
[root@client ~]#curl http://www.zhanggui.com
10.0.0.7
[root@client ~]#curl http://www.zhanggui.com
10.0.0.7
[root@client ~]#curl http://www.zhanggui.com
10.0.0.7
[root@client ~]#curl http://www.zhanggui.com
10.0.0.7
当把server 10.0.0.7:80 down;down后就会出现下面的结果。
[root@client ~]#curl http://www.zhanggui.com
10.0.0.17
[root@client ~]#curl http://www.zhanggui.com
10.0.0.17
[root@client ~]#curl http://www.zhanggui.com
10.0.0.17

最少连接数(least_conn)

最少连接调度算法,优先将客户端请求调度到当前连接最少的后端服务器,相当于LVS中的WLC(加权最少连接算法);同时要考虑服务器的权重值,如果后端服务器的连接数都相同时,则使用WRR加权轮询调度算法。
示例:

root@Nginx:~# vim /apps/nginx/conf/nginx.conf
#在http块中加上下面语句
upstream websrvs 
    least_conn;
    server 10.0.0.7:80;
    server 10.0.0.17:80;

root@Nginx:~# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
root@Nginx:~# nginx -s reload
#在客户端上测试数据
[root@client ~]#curl http://www.zhanggui.com
10.0.0.7
[root@client ~]#curl http://www.zhanggui.com
10.0.0.17
[root@client ~]#curl http://www.zhanggui.com
10.0.0.7
[root@client ~]#curl http://www.zhanggui.com
10.0.0.17
从上面数据来看,后端服务器的连接数都相同时,则使用WRR加权轮询调度算法,默认权重是1

Nginx核心算法的工作原理

一致性Hash算法工作原理


一致性Hash算法是常用关键算法之一,在分布式计算系统、分布式存储系统、数据分析等众多领域中广泛应用。 hash算法的关键在于它能够根据不同的属性数据,生成一串不相同的hash值,并且能够将这个hash值转换为 0 ~ (2的32次方-1) 范围整数,详细的查看上图中的圆环图。 对一台服务器的某个或者某一些属性进行hash计算(通常是这个服务器的IP地址和开放端口),并且根据计算分布在这个圆环上的某一个点。也就是图中圆环上的蓝色点。 对一个处理请求同样也可以根据这个请求的某一个或者某些属性进行hash计算(可以是这个请求的IP、端口、cookie值、URL值或者请求时间等),并且根据计算记过分布在这个圆环上的某一个点上。也就是上图圆环上的黄色点。 我们约定落在某一个蓝点A左侧和蓝点B右侧的黄色点所代表的请求,都有蓝点A所代表的服务器进行处理,这样就完成解决了“谁来处理”的问题。在蓝色点稳定存在的前提下,来自于同一个Hash约定的请求所落在的位置都是一样的,这就保证了服务处理客户请求相对的固定。​ 当某一个蓝色点由于某种原因下线,其所影响到的黄色点也是有限的。即下一次客户端的请求将由其他的蓝色点所代表的服务器进行处理。

轮询与加权轮询

当有任务需要传递到下层节点进行处理时,任务来源点会按照固定的顺序,将任务依次的分配下去如果下层可用的节点数量为X,那么第N个任务的分配规则为:目标节点=(NmodX)+1

轮询处理在很多架构思想中都有体现:DNS解析多IP时、LVS向下转发消息时、Nginx向下转发消息时、Zookeeper向计算节点分配任务时。了解基本的轮询过程有助于我们在进行软件架构设计时进行思想借鉴。但是上面的轮询方式是有缺陷的,由于各种客观原因我们可能无法保证任务处理节点的处理能力都是一样的(CPU、IO、内存频率等不同)。所以A节点业务能同时处理100个任务,但是B节点可能同时只能处理50个任务。在这种情况下我们需要依据下层节点某个或者多个属性设置权值。这个属性可能是网络带宽、CPU繁忙程度或者就是各一个固定的权值。

那么加权轮询的分配依据是什么呢?有很多分配依据,例如:概率算法(此算法中包括蒙特卡罗算法,拉斯维加斯算法和舍伍德算法,在网络上有很多介绍资料)、最大公约数法。这里我们对最大公约数算法进行介绍,因为该方法简单实用:

首先按照某种规则计算得到每个处理节点的权值,上文已经说到计算规则可能是这个服务节点的CPU利用率、网络占用情况或者在配置文件中的固定权重。
求这些权值的最大公约数,在上图中三个节点的权值分别是100、80、60.那么求得的最大公约数就是20(如果您忘记了最大公约数的定义,请自行复习)。那么这三个节点的被除结果分别是5、4、3,求和值为12。得到以上的计算结果,就可以开始进行请求分配了,公式同样为:(NmodX)+1=Y。其中N表示当前的第N次任务;X表示整除后的求和结果;Y为处理节点。
备注:加权轮询是轮询方案的补充,通过将处理节点的属性转换成权值可以有效的描述处理节点的处理能力,实现更科学的处理任务分配。加权轮询的关键在于加权算法,最大公约数算法简单实用,定位效率高。

以上是关于nginx负载均衡中常见的算法及原理的主要内容,如果未能解决你的问题,请参考以下文章

Nginx负载均衡中常见的算法及原理有哪些

Nginx负载均衡常见的算法

Ribbon负载均衡算法

运维高手三:nginx负载均衡常见架构及问题解析

NGINX

Nginx+Tomcat负载均衡及动静分离