7.2负载均衡常用算法
负载均衡常用算法主要有随机、加权随机、轮询、加权轮询、源地址hash等。
7.2.1软负载随机算法实现
随机算法原理为:获取服务列表大小范围内的随机数,将该随机数作为列表索引,从服务提供列表中获取服务提供者。
为负载均衡策略算法定义接口如下:
publicinterfaceClusterStrategy{
publicProviderServiceselect(ListproviderServices);
}
其中接口方法入参providerServices为服务提供者列表。
软负载随机算法的实现过程如下。
importares.remoting.framework.cluster.ClusterStrategy;
importares.remoting.framework.model.ProviderService;
importorg.apache.commons.lang3.RandomUtils;
importjava.util.List;
publicclassRandomClusterStrategyImplimplementsClusterStrategy{
@Override
publicProviderServiceselect(ListproviderServices){
intMAX_LEN=providerServices.size();
intindex=RandomUtils.nextInt(0,MAX_LEN-1);
returnproviderServices.get(index);
}
}
实现原理:获得服务提供者列表大小区间之间的随机数,作为服务提供者列表的索引来获取服务。
7.2.2软负载加权随机算法实现
加权随机算法在随机算法的基础上针对权重做了处理。软负载加权随机算法实现代码如下。
importares.remoting.framework.cluster.ClusterStrategy;
importares.remoting.framework.model.ProviderService;
importcom.google.common.collect.Lists;
importorg.apache.commons.lang3.RandomUtils;
importjava.util.List;
publicclassWeightRandomClusterStrategyImplimplementsClusterStrategy{
@Override
publicProviderServiceselect(ListproviderServices){
//存放加权后的服务提供者列表
ListproviderList=Lists.newArrayList();
for(ProviderServiceprovider:providerServices){
intweight=provider.getWeight();
for(inti=0;i
providerList.add(provider.copy());
}
}
intMAX_LEN=providerList.size();
intindex=RandomUtils.nextInt(0,MAX_LEN-1);
returnproviderList.get(index);
}
}
实现原理:首先根据加权数放大服务提供者列表,比如服务提供者A加权数为3,放大之后变为A,A,A,存放在新的服务提供者列表,然后对新的服务提供者列表应用随机算法。
7.2.3软负载轮询算法实现
轮询算法,将服务调用请求按顺序轮流分配到服务提供者后端服务器上,均衡对待每一台服务提供者机器。软负载轮询算法实现代码如下。
importares.remoting.framework.cluster.ClusterStrategy;
importares.remoting.framework.model.ProviderService;
importjava.util.List;
importjava.util.concurrent.TimeUnit;
importjava.util.concurrent.locks.Lock;
importjava.util.concurrent.locks.ReentrantLock;
publicclassPollingClusterStrategyImplimplementsClusterStrategy{
//计数器
privateintindex=0;
privateLocklock=newReentrantLock();
@Override
publicProviderServiceselect(ListproviderServices){
ProviderServiceservice=null;
try{
lock.tryLock(10,TimeUnit.MILLISECONDS);
//若计数大于服务提供者个数,将计数器归0
if(index>=providerServices.size()){
index=0;
}
service=providerServices.get(index);
index++;
}catch(InterruptedExceptione){
e.printStackTrace();
}finally{
lock.unlock();
}
//兜底,保证程序健壮性,若未取到服务,则直接取□□个
if(service==null){
service=providerServices.get(0);
}
returnservice;
}
}
实现原理:依次按顺序获取服务提供者列表中的数据,并使用计数器记录使用过的数据索引,若数据索引到□后一个数据,则计数器归零,重新开始新的循环。
……