AWebManCN

Menu

五分钟看懂 Nginx 负载均衡

什么是负载均衡

负载均衡(Load Balance),它在网络现有结构之上可以提供一种廉价、有效、透明的方法来扩展网络设备和服务器的带宽,并可以在一定程度上增加吞吐量、加强网络数据处理能力、提高网络的灵活性和可用性等。用官网的话说,它充当着网络流中“交通指挥官”的角色,“站在”服务器前处理所有服务器端和客户端之间的请求,从而最大程度地提高响应速率和容量利用率,同时确保任何服务器都没有超负荷工作。如果单个服务器出现故障,负载均衡的方法会将流量重定向到其余的集群服务器,以保证服务的稳定性。当新的服务器添加到服务器组后,也可通过负载均衡的方法使其开始自动处理客户端发来的请求。(详情可参考:What Is Load Balancing?

简言之,负载均衡实际上就是将大量请求进行分布式处理的策略。

什么是 Nginx 负载均衡

通过上文简单的概念介绍,你可能对负载均衡有了一个初步的了解,知道它是一种调度策略。那么问题来了,Nginx 又是什么呢?Nginx 如何实现负载均衡?这就要从正向代理和反向代理说起了。

负载均衡常用算法

1. 轮询 (round-robin)

轮询为负载均衡中较为基础也较为简单的算法,它不需要配置额外参数。假设配置文件中共有 M 台服务器,该算法遍历服务器节点列表,并按节点次序每轮选择一台服务器处理请求。当所有节点均被调用过一次后,该算法将从第一个节点开始重新一轮遍历。

特点:由于该算法中每个请求按时间顺序逐一分配到不同的服务器处理,因此适用于服务器性能相近的集群情况,其中每个服务器承载相同的负载。但对于服务器性能不同的集群而言,该算法容易引发资源分配不合理等问题。

2、加权轮询

为了避免普通轮询带来的弊端,加权轮询应运而生。在加权轮询中,每个服务器会有各自的 weight。一般情况下,weight 的值越大意味着该服务器的性能越好,可以承载更多的请求。该算法中,客户端的请求按权值比例分配,当一个请求到达时,优先为其分配权值最大的服务器。

特点:加权轮询可以应用于服务器性能不等的集群中,使资源分配更加合理化。

Nginx 加权轮询源码可见:ngx_http_upstream_round_robin.c,源码分析可参考:关于轮询策略原理的自我理解。其核心思想是,遍历各服务器节点,并计算节点权值,计算规则为 current_weight 与其对应的 effective_weight 之和,每轮遍历中选出权值最大的节点作为最优服务器节点。其中 effective_weight 会在算法的执行过程中随资源情况和响应情况而改变。较为核心的部分如下:

for (peer = rrp->peers->peer, i = 0;
	peer; 	/* peer 为当前遍历的服务器结点*/
  peer = peer->next, i++)
{
  ...
    
	/* 每轮遍历会更新 peer 当前的权值*/
	peer->current_weight += peer->effective_weight;

  ...
    
	/* best 为当前服务器中的最优节点,即本轮中选中的服务器节点*/
	if (best == NULL || peer->current_weight > best->current_weight) {
		best = peer;
  	p = i;
	}
  
  ...
}
复制代码

3. IP 哈希(IP hash)

ip_hash 依据发出请求的客户端 IP 的 hash 值来分配服务器,该算法可以保证同 IP 发出的请求映射到同一服务器,或者具有相同 hash 值的不同 IP 映射到同一服务器。

特点:该算法在一定程度上解决了集群部署环境下 Session 不共享的问题。

Session 不共享问题是说,假设用户已经登录过,此时发出的请求被分配到了 A 服务器,但 A 服务器突然宕机,用户的请求则会被转发到 B 服务器。但由于 Session 不共享,B 无法直接读取用户的登录信息来继续执行其他操作。

实际应用中,我们可以利用 ip_hash,将一部分 IP 下的请求转发到运行新版本服务的服务器,另一部分转发到旧版本服务器上,实现灰度发布。再者,如遇到文件过大导致请求超时的情况,也可以利用 ip_hash 进行文件的分片上传,它可以保证同客户端发出的文件切片转发到同一服务器,利于其接收切片以及后续的文件合并操作。

4、其他算法

应用场景

说了这么多理论,究竟基于 Nginx 的负载均衡要怎么用呢?接下来,将以加权轮询算法为例,带大家尝试通过自己的一台笔记本 + Nginx + Node 测试一下负载均衡。由于没有多台服务器,于是通过自己笔记本的多个不同端口来模拟不同的服务器。

Step 1:确保自己的电脑中,Nginx 已安装并能够成功启动(以 Mac 为例)

如果你也遇到了像我一样由于端口占用导致 Nginx 启动失败的问题,可以尝试下述步骤修改配置文件中的端口号

Step 2:基于 Node + Express 框架来搭建简单的服务器

Express 是一个简洁而灵活的轻量级 node.js Web 应用框架(详情可了解 Express),如果第一次使用,请先安装。

此处可以多起几个服务,分别让 Node 监听 8087,8088,8089 端口,每个服务中通过 send 不同的文案用以区分不同的 Server。

Step 3:在 nginx.conf 文件中配置好需要轮询的服务器和代理

upstream testServer {
  server localhost:8087 weight=10;
  server localhost:8088 weight=2;
  server localhost:8089;
}
复制代码
location / {
  root   html;
  index  index.html index.htm;
  proxy_pass http://testServer; // testServer 为自己定义的服务器集群
}	
复制代码

Step 4:查看结果

通过多次刷新可以发现,由于设置了不同的 weight,端口号为 8087 的服务器出现的次数最多,同时证实了权值越高,服务器处理请求几率越大的规则。

总结

Nginx 作为一款优秀的反向代理服务器,可以通过不同的负载均衡算法来解决请求量过大情况下的服务器资源分配问题。较为常见的负载均衡算法有轮询、加权轮询、IP 哈希等等,可分别应对不同的请求场景。如果有兴趣可以去 Github 理解下大神的源码,有问题也欢迎一起来探讨~

参考文献

推荐阅读

前端工程实践之可视化搭建系统(一)

可能是最全的 “文本溢出截断省略” 方案合集

图文并茂,为你揭开“单点登录“的神秘面纱
作者:政采云前端团队
链接:https://juejin.im/post/5e806d84e51d4546b659b370
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

— 于 共写了4429个字
— 文内使用到的标签:

发表评论

电子邮件地址不会被公开。 必填项已用*标注