山地人

Nginx 负载均衡

山地人
山地人
2021-07-26

什么是负载均衡

随着业务访问量的增加,原来单一的服务器已经无法支撑大量的访问。这时单一服务器就处于过载状态,为了缓解这种情况,让服务能够满足增长的访问量,就需要一种解决方案。让原本服务器的服务能力得到扩展,通常就是增加服务器,也就是横向扩展。然后找一种方法将大量请求分摊到不同的服务器上,让每台服务器都在自己的负荷下工作。这里负责分摊流量工作的行为就被称为负载均衡。

Nginx除了可以用来配置静态服务器或者反向代理外,也能用作负载均衡。

实现负载均衡

要实现负载均衡,我们需要完成几个步骤:

  1. 定义一组服务器,用于作为分摊负载的服务器,这个使用upstream指令来实现。
  2. 将要分摊的流量分配到这组服务器上。
  3. 设置流量的分配策略。

upstream指令

这条指令用于定义一组服务器。

语法默认值上下文(Context)
upstream name { … }-http
upstream backend {
server backend1.example.com weight=5;
server 127.0.0.1:8080 max_fails=3 fail_timeout=30s;
server unix:/tmp/backend3;
server backup1.example.com backup;
}
  • backend是我们为这组服务器定义的一个名称。
  • serverupstream里的每一个server对应了一台服务器。 上面的配置在backend服务器组中配置了4台服务器。

server指令

server指令用于定义一台服务器的相关信息。

语法默认值上下文(Context)
server address [parameters];-upstream
  • address部分可以是一个带端口的域名或者一个带端口的IP地址又或者是一个UNIX域的套接字路径。如果不指定端口默认使用80端口。
  • [parameters]是可选参数:
    • weight=number用于设置服务器的权重,默认权重为1。
    • max_conns=number设置服务器的最大连接数为number。默认值为0,表示不限制。
    • max_fails=number设置在fail_timeout持续时间内与服务器通讯失败的尝试次数。默认值为1。表示失败后尝试一次。如果设为0表示失败后不尝试。
    • fail_timeout=time设置失败尝试的持续时间,默认为10秒。
    • backup标记此服务器为备份服务器,当主服务器不可用时,请求会传递给备份服务器。
    • down标记此服务器为永久不可用。

现在分析下之前定义的backend服务器组里的服务器情况。

upstream backend {
server backend1.example.com weight=5;
server 127.0.0.1:8080 max_fails=3 fail_timeout=30s;
server unix:/tmp/backend3;
server backup1.example.com backup;
}
  • 前三台为主服务器,最后一台为备份服务器。
  • 第一台的权重是5,其他两台主服务器为默认权重1。也就意味着如果有7条请求过来,第一台服务器会接受5个请求,后两台服务器各接受1条请求。
  • 当前面的三台主服务器都不可用时,最后一台备份服务器会接受所有请求。
  • 其中第二台服务器如果收到请求失败,会在30秒内尝试最多3次重试。

流量导入

之后我们在http中定义了一个server,将所有的请求都通过proxy_pass反向代理到backend服务器组中。

http {
upstream backend {
server backend1.example.com;
server backend2.example.com;
server 192.0.0.1 backup;
}
server {
location / {
proxy_pass http://backend;
}
}
}

选择负载均衡策略

最后我们需要确定,如何对流量进行分发,在Nginx中内置了四种负载均衡的策略:

  1. Round Robin循环,这是默认的负载均衡策略,当不对upstream设置任何负载均衡策略时,Nginx会根据服务器组中的各台服务器的权重weight将请求按权重分配。
  2. least_conn请求会根据服务器上的活动连接数,活动连接数最少的服务器优先考虑,之后再考虑服务器的权重的一种分配策略。
  3. ip_hash 这种策略会根据客户端的IP地址来分配对应的服务器,保证相同的IP的请求能够到达同一台服务器。
  4. hash 这种策略下,允许Nginx配置人员自行决定将哪些因素作为哈希值的键。相当于ip_hash的自定义版本。
  5. least_time这种策略仅NGINX Plus版本支持。
  6. random 可以按照一定规则进行随机选择。

启动终端,然后运行代码,看代理服务器是否能正常工作。

动手实验

在上面的例子中,大致能看出前三台主服务器a,b,c大致按照2:1:1的比例分配请求。

现在测试一种一些服务器挂掉后,其他服务器是否能继续正常运转。

  1. 使用ps -aux | grep node在上面的沙盒终端中查询几台node服务器的pid(第2列值)。
  2. 使用kill -9 pid的方式杀死其中的一个node服务器。(将pid替换为你前面查询到的真实pid值)
  3. 然后刷新浏览器,观察剩余的几台服务器如何分配请求。
  4. 继续重复步骤2-3,观察现象。
  5. 当所有主服务器(端口为:8080、8081、8082)的node服务器都被kill后,最后的一台备份服务器(8083端口的srever-d)是否开始处理请求。