或许很多同学接触过负载均衡,大部分是来自于Nginx里配置的认识,一般情况下为了提高Tomcat的并发量都是基于Nginx做负载均衡,示例如下:
server{
listen 80;
server_name www.baidu.com;
#负载均衡池(推荐)
upstream tomcat1{
server 192.168.25.141:8080 weight=1;
server 192.168.25.142:8080 weight=2 max_fails=3 fail_timeout=30s;
#权重
#多少次失败之后,任务该服务挂了
#超时时间
}
#负载均衡池(ip_hash)
upstream tomcat2{
server 192.168.25.141:8080 weight=1;
server 192.168.25.142:8080 weight=2;
ip_hash;#每个ip永远只请求指定的ip,不需要做session处理
}
location / {
proxy_pass http://tomcat1;
}
}
类似Nginx这种负载均衡器,它主要是一个代理层,但是很多情况下,我们需要手工去实现自己的负载均衡功能,当然,一般在中间件开发当中遇到的比较多(业务系统相对少一点),场景案例如下:
①Dubbo,客户端发起调用的时候,需要从多个地址里面选择一个进行调用
②SpringCloud体系里面的Ribbon负载均衡器
③分布式文件系统(FastDFS,HDFS),文件上传的时候,首先需要去管理节点获取具体的存储节点的IP信息,这个时候,管理节点需要实现负载均衡算法
思考:如果领导让我们实现一个分布式任务调度中间件,我们应该怎么实现呢?
方案描述: ①基于Zookeeper实现分布式锁;②到执行时间点时,定时任务工程则去获取分布式锁,谁抢到锁,谁有执行权限。
方案优点: ①思路简单;②实现起来比较容易
方案缺点: ①每个定时工程实现比较复杂,需要手工集成定时器(不同人开发可能选择不同的定时器技术,去定时线程池、JDK Timer、Spring Task、Quartz等,技术得不到统一);②无法有效的管理所有定时任务,实现在线控制任务的状态(暂停、停止、启动等)
方案描述: ①每个定时工程只需要实现某个标准接口即可,无需关系定时器问题;②每个定时工程启动的时候连接管理节点,并且把所有定时作业注册到管理节点(封装好Client客户端);③管理节点本身集成定时器,并且提供在线管理每个定时作业的状态;④管理节点通过远程触发的方式去触发具体某个定时工程去执行。
方案优点: ①定时工程开发比较简单;②管理节点具备强大的功能,可以统一管理所有的定时作业
方案缺点: 实现起来会稍微复杂点
回归正题,管理节点在实现远程触发的时候,它必须实现负载策略去选择具体的节点执行任务。这基本上就是开发一个中间件的常见思路了(跟业务系统思想上是存在区别的)
首先,如果去实现常见的负载均衡算法呢?
首先,我们先了解常见的负载均衡算法的种类:①随机;②轮询;③随机+权重;④轮询+权重;⑤最小连接数;
负载均衡的UML图
描述:定义一个接口,然后不同类型的负载算法对应不同的实现类
优点:思路简单
缺点:①每个实现类都需要做一些重复的判断工作,比如:List是否为空,如果List只有一条记录的情况直接返回;②具体选择哪个策略完全让用户自己去选择,不是很好
描述:①增加一个抽象类,抽象类的作用是做一些通用的工作(比如:判断List是否为空,是否等于1);②增加一个策略类,目的是解耦负载算法和业务的关系。
其次,常见负载算法的大概实现思路是什么呢?
①随机,思路很简单,就是通过Random生成一个随机数,这个随机数就是List的下标值。
②轮询,通过一个全局变量控制当前取值的位置,每次取值时,该值加1,如果一旦该值大于等于List的长度,则重置。
③权重+随机|轮询,核心是如何实现权重呢?其实很简单,根据每条记录的权重值,生成对应比例的数据放到一个新集合即可,这样的话,最后取值的概率跟权重比是一致的。
最后,长连接情况下,负载均衡算法会存在什么问题呢?
在短连接的情况下,请求完成之后释放连接资源,这样情况下即使负载失衡产生的影响也不至于很大,但是长连接它是建立连接之后可以多次通讯不立马释放资源,一旦负载失衡,那么将会导致连接过多的服务器压力过大。请看下面的具体分析:
情况一: 最小连接数算法
描述:最小连接数,通过判断哪个服务器的连接数最小,然后选择连接到该服务器
缺点:①如果某个服务器一旦宕机,重启之后,那么它的连接数最小,大量的连接就会涌进来,导致该服务器压力非常的大;②如果新增一个服务器节点,那么道理是一样的。
情况二: 轮询算法
描述:通过轮询的方式把连接平均的分配给每个服务器
缺点:①如果某个服务器一旦宕机,重启之后,它的连接数永远最小,造成每个服务器的连接数不够平衡;②如果新增一个服务器节点,那么道理是一样的。
解决思路:采用轮询算法,并且给每个连接设置生命周期,比如:通过心跳检查如果该连接没有数据包时,则断开连接,让连接重连,这样的话,会逐渐让每个服务器的连接数保持平衡。
负载均衡算法的Demo源码:
https://gitee.com/zwyyf/demo-loadbalance.git
慕课网专栏(架构思维成长之微服务+仿百度网盘源码):
https://www.imooc.com/read/73
共同学习,写下你的评论
评论加载中...
作者其他优质文章