Nginx 轮询算法

负载均衡

一般的反向代理服务器,都具备负载均衡的功能。负载均衡功能可以由硬件来提供,比如以前的F5设备。
也可以由软件来提供,LVS可以提供四层的负载均衡(利用IP和端口),Haproxy和Nginx可以提供七层的负载均衡(利用应用层信息)。
像nginx可以使用负载均衡分配流量,ribbon为客户端提供负载均衡,dubbo服务调用里的负载均衡等等,很多地方都使用到了负载均衡。

负载均衡有好几种实现策略,常见的有:

  • 随机 (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,一致性哈希,可减少缓存数据的失效。

简单轮询算法

描述IP
第一台服务器192.168.1.1
第二台服务器192.168.1.2
第三台服务器192.168.1.3

第一个请求过来之后默认访问第一台,第二个请求过来访问第二台,第三次请求过来访问第三台,第四次请求过来访问第一台,以此类推。
此时如果我有一台服务器性能比较好(比如192.168.1.1),我想让这台服务器处理多一点请求,此时就涉及到了权重得概率,这种算法就不能实现。

加权轮询算法

来看一个简单的Nginx负载均衡配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
http {
upstream cluster {
server a weight=5;
server b weight=1;
server c weight=1;
}

server {
listen 80;

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

此时前5个请求都会访问到第一台服务器,第六个请求会访问到第二台服务器,第七个请求会访问到第三台服务器。

其实这种算法有一个缺点,后端序列是这样的:{ c, b, a, a, a, a, a },会有5个连续的请求落在后端a上,分布不太均匀。如果我第一台服务器设置权重过大可能我很多次请求都执行到第一台服务器上去,会造成某一台服务器压力过大导致崩溃。

平滑加权轮询算法

由上图可以看出第一台服务器虽然权重设置的是5,但并不是第五次请求过来都是第一台服务器执行,而是分散执行,调度序列是非常均匀的,且第 7 次调度时选中后当前权重又回到 {0, 0, 0},实例的状态同初始状态一致,所以后续可以一直重复调度操作。

这里大概描述一下:

1.首先总权重不会变,默认就是当前设置的权重之和

2.在第一次请求进来的时候我默认初始化当前权重选中值是{0,0,0},所以当前权重的值就是{5+0,1+0,1+0},这里的5,1,1就是我们前面每台服务器设置的权重。

3.这里我们可以得出第一次请求过来的最大权重是5。然后返回第一台服务器ip

4.然后我们设置选中后当前权重,这里就是当前最大权重减去总权重(5-7),没有选中的权重不变,这时候得到当前权重选中权重的值{5-7,1,1}

5.在第二次请求过来的时候我们延续上面的2,3,4步骤执行.


Nginx 轮询算法
https://www.panaihua.com/nginx-poll/
作者
谏言
发布于
2022年5月20日
许可协议