我们使用Nginx来做反向代理的时候,可以顺便实现负载均衡,本文介绍几种常见负载均衡算法。

一、轮询

轮询,即反向代理服务器将负载轮流分配至各业务服务器,雨露均沾,不偏不向。

nginx-lb-polling

准备工作,先准备两台业务服务器(即图中的“192.168.0.200”和“192.168.0.201”),并各自启动Nginx,且在Nginx的html/下新增ip.html文件如下:

1
2
3
4
5
6
7
8
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<p>current ip: <此处改成当前机器的IP></p>
</body>
</html>

确保访问各自ip的ip.html文件都能进入该页面,并且展示当前服务器的IP。

此时,开始配置反向代理的服务器,即图中的“192.168.0.199”:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# 此处只列出了有改动的配置
http {
    # 定义一个服务器组,命名为my_test
    upstream my_test {
        server 192.168.0.200;
        server 192.168.0.201;
    }
    server {
        location / {
             proxy_pass   http://my_test;
        }
    }
}

搞定之后,刷新配置文件,访问“192.168.0.199/ip.html”,此时便可以发现,一下访问到“192.168.0.200”,一下访问到“192.168.0.201”。

二、加权轮询

该方案本质上也是轮询,但是它是一种特殊的轮询,因为它带有了权重。

考虑如下场景,有两台业务服务器对外提供服务,但一台性能强,一台性能弱,此时便可以按照配置的权重将不等量的负载分别给到这两台服务器,从而避免高配置服务器的性能浪费以及低配置服务器的资源紧张导致的不稳定。

nginx-lb-weight

按照上述假设,我们配置分配到“192.168.0.200”和“192.168.0.201”的请求比例为2比1,即每3次请求中有2次分配到性能较强的“192.168.0.200”,1次分配到性能较弱的“192.168.0.201”。

配置方法在普通轮询的基础上设置服务器的权重即可:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# 此处只列出了有改动的配置
http {
    # 定义一个服务器组,命名为my_test
    upstream my_test {
        server 192.168.0.200 weight=2;
        server 192.168.0.201 weight=1;
    }
    server {
        location / {
             proxy_pass   http://my_test;
        }
    }
}

刷新配置文件,访问“192.168.0.199/ip.html”,此时便可以发现,两次访问到“192.168.0.200”,接着一次访问到“192.168.0.201”,如此循环。

在如上配置服务器组时,我们还可以给某些服务器指定一些关键字,例如:

down,本服务器永远不参与轮询。

backup,本服务器作为后备服务器,在平时不参与轮询,当其他服务器不能提供服务时,当前服务器才参与轮询。

三、最小连接数

该算法可以将每次请求分配到活跃连接数最少的服务器上去。

该方法的配置方式很简单,即在服务器组中添加least_conn;,如下所示:

1
2
3
4
5
upstream my_test {
    least_conn;
    server 192.168.0.200 weight=2;
    server 192.168.0.201 weight=1;
}

注意,当满足条件的服务器有多台时,例如两台服务器连接数都是5,那么此时就考虑权重来分配到具体的服务器。

四、IP哈希

由于HTTP协议的一大特点就是无状态,刚刚客户端和服务端还在连接交互数据,紧接着的下一次连接双方就互不认识了,也不记得上次发生了什么。为了解决一些必须让双方“拥有记忆”的场景,后来就有了Cookie和Session,这其中Session是存在服务器端的,用于帮助服务端记录客户端的信息。

而如果负载均衡时本次连接的服务器与上一次连接时不是同一台,那么服务端就仍然不“认识”客户端了,为了解决这个问题,可以使用“IP哈希”的负载均衡算法。这种算法会依据客户端的IP进行计算,然后将来自于同一IP的请求固定分配至一台服务器。

而使用IP哈希算法的方式也很简单,类似最小连接数:

1
2
3
4
5
upstream my_test {
    ip_hash;
    server 192.168.0.200;
    server 192.168.0.201;
}

参考资料: