负载均衡
负载均衡策略是服务的重要属性,分布式服务框架通常会提供多种负载均衡策略,同时支持用户扩展负载均衡策略 。
随机
通常在对等集群组网中,采用随机算法进行负载均衡,随机路由算法消息分发还是比较均匀的,采用 JDK 提供的 java.util.Random 或者 java.security.SecureRandom 在指定服务提供者列表中生成随机地址 。
消费者基于随机生成的服务提供者地址进行远程调用:
/***随机*/publicclassRandomStrategyimplementsClusterStrategy{@OverridepublicRemoteServiceBaseselect(List<RemoteServiceBase>list){intMAX_LEN=list.size();intindex=RandomUtil.nextInt(MAX_LEN);returnlist.get(index);}}
随机还是存在缺点的,可能出现部分节点的碰撞的概率较高,另外硬件配置差异较大时,会导致各节点负载不均匀 。
为避免这些问题,需要对服务列表加权,性能好的机器接收的请求的概率应该高于一般机器:
/***加权随机*/publicclassWeightingRandomStrategyimplementsClusterStrategy{@OverridepublicRemoteServiceBaseselect(List<RemoteServiceBase>list){//存放加权后的服务提供者列表List<RemoteServiceBase>weightingList=newArrayList<RemoteServiceBase>();for(RemoteServiceBaseremoteServiceBase:list){//扩大10倍intweight=(int)(remoteServiceBase.getWeight()*10);for(inti=0;i<weight;i++){weightingList.add(remoteServiceBase);}}intMAX_LEN=weightingList.size();intindex=RandomUtil.nextInt(MAX_LEN);returnweightingList.get(index);}}
轮询
逐个请求服务地址,到达边界之后,继续绕接 。主要缺点:慢的提供者会累积请求 。
例如第二台机器很慢,但没挂 。当请求第二台机器时被卡在那 。久而久之,所有请求都卡在第二台机器上 。
轮询策略实现非常简单,顺序循环遍历服务提供者列表,达到边界之后重新归零开始,继续顺序循环:
/***轮询*/publicclassPollingStrategyimplementsClusterStrategy{//计数器privateintindex=0;privateLocklock=newReentrantLock();@OverridepublicRemoteServiceBaseselect(List<RemoteServiceBase>list){RemoteServiceBaseservice=null;try{lock.tryLock(10,TimeUnit.MILLISECONDS);//若计数大于服务提供者个数,将计数器归0if(index>=list.size()){index=0;}service=list.get(index);index++;}catch(InterruptedExceptione){e.printStackTrace();}finally{lock.unlock();}//兜底,保证程序健壮性,若未取到服务,则直接取第一个if(service==null){service=list.get(0);}returnservice;}}
加权轮询的话,需要给服务地址添加权重:
/***加权轮询*/publicclassWeightingPollingStrategyimplementsClusterStrategy{//计数器privateintindex=0;//计数器锁privateLocklock=newReentrantLock();@OverridepublicRemoteServiceBaseselect(List<RemoteServiceBase>list){RemoteServiceBaseservice=null;try{lock.tryLock(10,TimeUnit.MILLISECONDS);//存放加权后的服务提供者列表List<RemoteServiceBase>weightingList=newArrayList<RemoteServiceBase>();for(RemoteServiceBaseremoteServiceBase:list){//扩大10倍intweight=(int)(remoteServiceBase.getWeight()*10);for(inti=0;i<weight;i++){weightingList.add(remoteServiceBase);}}//若计数大于服务提供者个数,将计数器归0if(index>=weightingList.size()){index=0;}service=weightingList.get(index);index++;returnservice;}catch(InterruptedExceptione){e.printStackTrace();}finally{lock.unlock();}//兜底,保证程序健壮性,若未取到服务,则直接取第一个returnlist.get(0);}}
服务调用时延
消费者缓存所有服务提供者的调用时延,周期性的计算服务调用平均时延 。
然后计算每个服务提供者服务调用时延与平均时延的差值,根据差值大小动态调整权重,保证服务时延大的服务提供者接收更少的消息,防止消息堆积 。
该策略的特点:保证处理能力强的服务接受更多的消息,通过动态的权重分配消除服务调用时延的震荡范围,使所有服务的调用时延接近平均值,实现负载均衡 。
一致性哈希
相同参数的请求总是发送到统一服务提供者,当某一台服务提供者宕机时,原本发往根提供者的请求,基于虚拟节点,平摊到其他提供者,不会引起剧烈变动,平台提供默认的虚拟节点数,可以通过配置文件修改虚拟节点个数 。
一致性 Hash 环工作原理如下图所示:

文章插图
一致性哈希
路由规则
负载均衡只能保证服务提供者压力的平衡,但是在一些业务场景中需要设置一些过滤规则,比较常用的是基本表达式的条件路由 。
推荐阅读
- 这一次,让你完全理解 HTTPS 到底是如何做到数据传输安全的
- 黑客是如何控制你手机的?出现这几种情况,你的手机可能已中招
- 经常练太极拳可以降低血糖是真的吗?
- 太极拳和阴阳五也行之间的关系是怎样的
- 你必须掌握的太极拳要领
- 太极拳居然有这功效 我震惊了
- 揭秘太极拳实战有什么作用
- 什么是掤劲 掤劲的训练方法
- 静功缠丝太极拳的创始人是谁
- 杨氏太极拳24式分别是什么
