一、负载均衡
今天学习一下Nginx的负载均衡。由于传统软件建构的局限性,加上一台服务器处理能里的有限性,在如今高并发、业务复杂的场景下很难达到咱们的要求。但是若将很多台这样的服务器通过某种方式组成一个整体,并且将所有的请求平均的分配给这些机器处理,那么这个“系统”就能处理尽可能多的请求,这就是负载均衡最初的设计思想。
当然可以使用的技术包含软件、硬件,咱们本次就着重谈谈Nginx的负载均衡。下图是一个四层 + 七层的负载均衡。采用lvs+nginx的拓扑结构。
二、负载均衡概念
1、什么是负载均衡
负载均衡,简称LB(Load Balancing),是一种计算机技术。用来在多个计算机(计算机集群)、网络连接、CPU、磁盘驱动器或其他资源中分配负载,以达到最优化资源使用、最大化吞吐率、最小化响应时间、同时避免过载的目的。宏观上的意思是将负载(工作任务,访问请求)进行平衡、分摊到多个操作单元(服务器,组件)上进行执行以解决高性能,单点故障(高可用),扩展性(水平伸缩)等高流量下常见的问题。
2、负载均衡分类
由于载均衡技术是要对网络传输中的报文进行控制,涉及到网络七层模型,因此负载均衡分类可以按照网络层次进行分类,比如二层、三层、四层、七层负载均衡。其中最常见的是四层和七层负载均衡。此外,还有其他方面进行分类的,有软衡、硬件负载均衡等,比如SpringCloud全家桶中的Eureka组件、各种分库分表的中间件都属于负载均衡的范畴。二层、三层、四层、七层负载均衡都都工作在OSI模型,接下来会对做一个简单的解释。业界已经有很多开源的负载均衡工具,大部分是工作在第四层和第七层的。代表的开源工具有Nginx、LVS、Haproxy。LVS 主要用来做四层负载均衡,Nginx 和 Haproxy 主要是做七层的负载均衡,但它们都支持四层的负载均衡,例如在 Nginx 中的 stream 模块除了支持四层的反向代理功能,也支持四层负载均衡功能。
2.1 二层负载均衡
负载均衡服务器对外提供一个VIP(虚拟IP),集群中不同的机器采用相同IP地址,但是机器的MAC地址不一样。当负载均衡服务器接受到请求之后,通过改写报文的目标MAC地址的方式将请求转发到目标机器实现负载均衡。二层负载均衡发生在数据链路层,所以也称为“数据链裤层负载均衡”它是属于OSI模型。
2.2 三层负载均衡
负载均衡服务器对外提供一个VIP(虚拟IP),但是集群中不同的机器采用不同的IP地址。当负载均衡服务器接受到请求之后,根据不同的负载均衡算法,通过IP将请求转发至不同的真实服务器。三层负载均衡发生在网络层故又称为“网络层负载均衡”,同样的它也是属于OSI模型。
2.3 四层负载均衡
四层负载均衡工作在OSI模型的传输层,由于在传输层,只有TCP/UDP协议,这两种协议中除了包含源IP、目标IP以外,还包含源端口号及目的端口号。四层负载均衡服务器在接受到客户端请求后,以后通过修改数据包的地址信息(IP+端口号)将流量转发到应用服务器。
2.4 七层负载均衡
七层负载均衡工作在 OSI 模型的应用层,应用层协议较多,常用 http、dns 等。七层负载就可以基于这些协议来负载。这些应用层协议中会包含很多有意义的内容。比如同一个 Web 服务器的负载均衡,除了根据 IP 加端口进行负载外,还可根据七层的 URL、浏览器类别、语言来决定是否要进行负载均衡。
3、负载均衡算法
负载均衡算法可以分成两大类,一类是静态的负载均衡算法,常见的有轮询、权重等;另一大类动态的负载均衡算法,常见的有最少的连接、最快响应、服务类型、服务质量等等。下面就着重记录几种常用的负载均衡算法。
3.1 轮询 (默认)
每一个来自网络中的请求,轮流分配给内部的服务器,从 1 到 N 然后重新开始。此种负载均衡算法适合服务器组内部的服务器都具有相同的配置并且平均服务请求 相对均衡的情况。
3.2 加权轮询(weight)
根据服务器的不同处理能力,给每个服务器分配不同的权值,使其能够接受相应权值数的服务请求。例如:服务器 A 的权值被设计成 1,B 的权值是 3,C 的权值是6,则服务器 A、B、C 将分别接受到 10%、30%、60% 的服务请求。此种均衡算法能确保高性能的服务器得到更多的使用率,避免低性能的服务器负载过重。
3.2 ip-hash(ip_hash)
我们都知道,每个请求的客户端都有相应的 ip 地址,该均衡策略中,nginx 将会根据相应的 hash 函数,对每个请求的 ip 作为关键字,得到的 hash 值将会决定将请求分发给相应 Server 进行处理。iphash算法的情况下,每一个IP在不变的情况下都会路由到首次请求的服务上。
3.2 最少连接数(least_conn)
最少连接,也就是说 nginx 会判断后端集群服务器中哪个 Server 当前的 Active Connection 数是最少的,那么对于每个新进来的请求,nginx 将该其分发给对应的 Server。
- Nginx中的负载均衡配置
Nginx 的 stream 模块和 http 模块分别支持四层和七层模块的负载均衡。其用法和支持的负载均衡策略大致相同。首先使用 upstream 指令块 和 server 指令指定上游的服务,upstream 指令的用法如下
upstream name { ... }
官网示例如下:下面定义了4台服务器,分别是域名、IP+端口、socket形式指定地址,默认情况下upstream指令块中采用的是加权轮训的方式轮询配置得服务,当然我们可以指定一些服务的静态配置,比如注定服务的权重、server的最大并发连接max_conns,(max_fails 和 fail_timeout)失败几次之后将服务标记为故障服务,在设置的时间内不在路由到标记为故障的服务。
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;
}
三、 负载均衡实践
基础知识梳理完毕,接下来进行实践来感受一下相关的概念,俗话说的:好纸上得来终觉浅,绝知此事要躬行!希望可以通过这些实验让咱们更加巩固这些技术点。
1、Nginx中负载均衡
环境准备:mac,我这边使用的是docker安装的nginx,安装教程可以根据我的这篇文章:传送门:Nginx教程,两给SpringBoot服务。首先咱们搭建环境。因为我们之前学习过docker挂载,所以这次修改Nginx文件就方便很多,需要的同学可以参考:docker 挂载、修改文件,如果没有进行挂载想要修改文件的可以参考这篇文章。废话不多说直接上case.
1.1 两个微服务
首先提供两个微服务模拟一份代码两台机器。两个服务都有一个路径相同的对外接口。
@RestController
@Slf4j
public class Demo1LBController {
@GetMapping("/lb/start")
public String demo1() {
String str = "demo1 lb start ...";
log.info(str);
System.out.println(str);
return str;
}
}
@RestController
@Slf4j
public class Demo2LBController {
@GetMapping("/lb/start")
public String demo2() {
String str = "demo2 lb start ...";
log.info(str);
System.out.println(str);
return str;
}
}
1.2 Nginx配置修改
upstream 块在http块中,用于设置一系列的后端服务器,设置反向代理及后端服务器的负载均衡。咱们定义负载均衡的服务叫做:myserver,然后在 server 块里的 location 配置代理:proxy_pass http://myserver;。
nginx.config里的配置
# ######## 负载均衡开始 ########
upstream myserver {
server 10.33.148.23:8081;
server 10.33.148.23:8082;
# 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;
}
# ######## 负载均衡结束 ########
default.config里的配置
location / {
root /usr/share/nginx/html;
index index.html index.htm;
proxy_pass http://myserver;
}
1.2 验证
咱们启动NG之后,在浏览器输入:http://localhost:8010/lb/start,即可得到请求到不同服务的返回,默认走的轮询所以都是规律性的返回。
2、轮询
轮询的配置就是不设置任何静态参数,采用 Nginx 默认的负载均衡策略,上面的验证就是,我这边就做赘述。
3、加权轮询
顾名思义就是根据服务器的不同处理能力,给每个服务器分配不同的权值。具体配置如下,8081的服务权重占4/5,大家可以在浏览器操作感受一下。
4、ip_hash
每个请求按访问 ip 的 hash 结果分配,这样每个访客固定访问一个后端服务器,可以解决 session 的问题。配置上ip hash之后即使有权重也不会重新请求其他的服务上。大家可以操作感受。
ip_hash;
5、参数说明
weight=number 设定服务器的权重,默认是1,权重越大被访问机会越大,可以根据机器的配置情况来配置。
max_fails=number 设定Nginx与服务器通信的尝试失败的次数。在fail_timeout参数定义的时间段内,如果失败的次数达到此值,Nginx就认为服务器不 可用。在下一个fail_timeout时间段,服务器不会再被尝试。 失败的尝试次数默认是1。
默认配置时,http_404状态不被认为是失败的尝试。 可以通过指令proxy_next_upstream 和memcached_next_upstream来配置什么是失败的尝试。
fail_timeout=time
统计失败尝试次数的时间段。在这段时间中,服务器失败次数达到指定的尝试次数,服务器就被认为不可用。默认情况下,该超时时间是10秒。
backup
标记为备用服务器。当主服务器不可用以后,请求会被传给这些服务器,配置这个指令可以实现故障转移。
down 标记服务器永久不可用,可以跟ip_hash指令一起使用。
负载均衡的相关知识就梳理完毕啦,本次对 Nginx 中的负载均衡的相关配置指令,实战 Nginx 的负载均衡功能,同时测试多种负载均衡算法的学习和记录希望可以帮助大家更好的里解Nginx。
版权归原作者 阳仔的屁仔 所有, 如有侵权,请联系我们删除。