当前位置:   article > 正文

Nginx负载均衡的4种方式 :轮询-Round Robin 、Ip地址-ip_hash、最少连接-least_conn、加权-weight=n_nginx 最小连接

nginx 最小连接

负载均衡的概念:

Load Balance负载均衡是用于解决一台机器(一个进程)无法解决所有请求而产生的一种算法。

我们知道单台服务器的性能是有上限的,当流量很大时,就需要使用多台服务器来共同提供服务,这就是所谓的集群。

负载均衡服务器,就是用来把经过它的流量,按照某种方法,分配到集群中的各台服务器上。

这样一来不仅可以承担更大的流量、降低服务的延迟,还可以避免单点故障造成服务不可用。

一般的反向代理服务器,都具备负载均衡的功能。负载均衡功能可以由硬件来提供,比如以前的F5设备。

也可以由软件来提供,LVS可以提供四层的负载均衡(利用IP和端口),Haproxy和Nginx可以提供七层的负载均衡(利用应用层信息)。

像nginx可以使用负载均衡分配流量,ribbon为客户端提供负载均衡,dubbo服务调用里的负载均衡等等,很多地方都使用到了负载均衡。

使用负载均衡带来的好处很明显:
当集群里的1台或者多台服务器down的时候,剩余的没有down的服务器可以保证服务的继续使用
使用了更多的机器保证了机器的良性使用,不会由于某一高峰时刻导致系统cpu急剧上升
负载均衡有好几种实现策略,常见的有:

随机 (Random)
轮询 (RoundRobin)
一致性哈希 (ConsistentHash)
哈希 (Hash)
加权(Weighted)

Nginx目前提供的负载均衡模块:
ngx_http_upstream_round_robin,加权轮询,可均分请求,是默认的HTTP负载均衡算法,集成在框架中。
ngx_http_upstream_ip_hash_module,IP哈希,可保持会话。
ngx_http_upstream_least_conn_module,最少连接数,可均分连接。
ngx_http_upstream_hash_module,一致性哈希,可减少缓存数据的失效。

1、轮询

轮询即Round Robin,根据Nginx配置文件中的顺序,依次把客户端的Web请求分发到不同的后端服务器。
配置的例子如下:

http{ 
 upstream sampleapp { 
   server <<dns entry or IP Address(optional with port)>>; 
   server <<another dns entry or IP Address(optional with port)>>; 
 } 
 .... 
 server{ 
   listen 80; 
   ... 
   location / { 
    proxy_pass http://sampleapp; 
   }  
 } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

上面只有1个DNS入口被插入到upstream节,即sampleapp,同样也在后面的proxy_pass节重新提到。

实例:

http {  

    upstream myservers{  

        server 134.56.56.4:8001; 
        server 134.56.56.4:8002;  
        server 134.56.52.4:8011;  
        server 134.56.52.4:8012;  

    }  
   
    server {  
        listen 80;  
  
        location / {  
            proxy_pass http://myservers;  
        }  
    }  

}  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

2、最少连接

Web请求会被转发到连接数最少的服务器上。

们知道轮询算法是把请求平均的转发给各个后端,使它们的负载大致相同。

这有个前提,就是每个请求所占用的后端时间要差不多,如果有些请求占用的时间很长,会导致其所在的后端负载较高。在这种场景下,把请求转发给连接数较少的后端,能够达到更好的负载均衡效果,这就是least_conn算法。

least_conn算法很简单,首选遍历后端集群,比较每个后端的conns/weight,选取该值最小的后端。

如果有多个后端的conns/weight值同为最小的,那么对它们采用加权轮询算法。

配置的例子如下:

upstream zf{
		least_conn;
		server localhost:8081;
		server localhost:8082;
		server localhost:8083;
	}
 
	server {
		listen 80;
		server_name www.xx.com;
		location /{
			proxy_pass http://zf;
		}
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

上面的例子只是在upstream节添加了least_conn配置。其它的配置同轮询配置。
listen 表示监听的端口号

server_name 表示访问的主机名

location 表示处理的请求地址,一个server中可以配置多个location

server 表示虚拟服务器,一个http中可以配置多个server

upstream 用于配置一组服务器地址供后续使用

发现问题

在公司里,有三台服务器,A服务器采购于2000年,最高处理并发数100,B服务器采购于2010年。最高处理并发数500,C服务器采购于2018年,最高处理并发数1000。如果,此时A服务器处理请求数为99,B服务器处理请求数为300,C服务器请求数为500,如果是你,进行分配资源的话,我想更倾向于C服务器吧,C虽然处理了很多请求,但是任然没有到达它的处理瓶颈。但是,根据最小连接数的规则,这条请求应该是A服务器处理,但很有可能就是压死骆驼的最后一根稻草。所以,给大家在介绍一种处理规则,基于权重的负载均衡方式。

权重方式

基于权重的负载均衡方式,Nginx会根据服务器设置的权重,进行合理分配请求连接数。

实现:

upstream zf{
		server localhost:8081 weight=5;
		server localhost:8082 weight=3;
		server localhost:8083 down;
	}
 
	server {
		listen 80;
		server_name www.xx.com;
		location /{
			proxy_pass http://zf;
		}
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

通过设置weight的比重,来进行资源分配。

补充两个关键字:

down,表示当前服务器不参与负载均衡。
backup,预留的备份服务器。当其他所有的非backup机器出现故障或者忙的时候,才会请求backup机器,因此这台机器的压力最轻。

3、IP地址哈希

前述的两种负载均衡方案中,同一客户端连续的Web请求可能会被分发到不同的后端服务器进行处理,因此如果涉及到会话Session,那么会话会比较复杂。

常见的是基于数据库的会话持久化。

要克服上面的难题,可以使用基于IP地址哈希的负载均衡方案。

这样的话,同一客户端连续的Web请求都会被分发到同一服务器进行处理。

ip_hash算法的原理很简单,根据请求所属的客户端IP计算得到一个数值,然后把请求发往该数值对应的后端。

所以同一个客户端的请求,都会发往同一台后端,除非该后端不可用了。ip_hash能够达到保持会话的效果。

ip_hash是基于round robin的,判断后端是否可用的方法是一样的。

第一步,根据客户端IP计算得到一个数值。

hash1 = (hash0 * 113 + addr[0]) % 6271;

hash2 = (hash1 * 113 + addr[1]) % 6271;

hash3 = (hash2 * 113 + addr[2]) % 6271;

hash3就是计算所得的数值,它只和初始数值hash0以及客户端的IP有关。

第二步,根据计算所得数值,找到对应的后端。

w = hash3 % total_weight;

while (w >= peer->weight) {

w -= peer->weight;

peer = peer->next;

p++;
  • 1
  • 2
  • 3
  • 4
  • 5

}

total_weight为所有后端权重之和。遍历后端链表时,依次减去每个后端的权重,直到w小于某个后端的权重。

选定的后端在链表中的序号为p。因为total_weight和每个后端的weight都是固定的,所以如果hash3值相同,

则找到的后端相同。

配置的例子如下:

http{
upstream sampleapp {
ip_hash;
server <<dns entry or IP Address(optional with port)>>;
server <<another dns entry or IP Address(optional with port)>>;
}

server{
listen 80;

location / {
proxy_pass http://sampleapp;
}
}

上面的例子只是在upstream节添加了ip_hash配置。其它的配置同轮询配置。

4、基于权重的负载均衡

基于权重的负载均衡即Weighted Load Balancing,这种方式下,我们可以配置Nginx把请求更多地分发到高配置的后端服务器上,把相对较少的请求分发到低配服务器。

这就是所谓的加权轮询,看起来很简单,但是最早使用的加权轮询算法有个问题,就是7个请求对应的

后端序列是这样的:{ c, b, a, a, a, a, a },会有5个连续的请求落在后端a上,分布不太均匀。

目前使用的加权轮询叫做平滑的加权轮询(smooth weighted round-robin balancing),它和前者的区别是:

每7个请求对应的后端序列为 { a, a, b, a, c, a, a },转发给后端a的5个请求现在分散开来,不再是连续的。

配置的例子如下:

http{
upstream sampleapp {
server <<dns entry or IP Address(optional with port)>> weight=2;
server <<another dns entry or IP Address(optional with port)>>;
}

server{
listen 80;

location / {
proxy_pass http://sampleapp;
}
}

上面的例子在服务器地址和端口后weight=2的配置,这意味着,每接收到3个请求,前2个请求会被分发到第一个服务器,第3个请求会分发到第二个服务器,其它的配置同轮询配置。

还要说明一点,基于权重的负载均衡和基于IP地址哈希的负载均衡可以组合在一起使用。

关于多节点集群部署带来的session问题,我使用了缓存技术,缓存可以使用memcached,也可以使用redis。

由于srping-session 和spring-data-redis由很好的支持,所以我采用了redis解决session共享问题。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/648690
推荐阅读
相关标签
  

闽ICP备14008679号