12.0、springcloud-Ribbon-自定义负载均衡算法【简单初体验】
咱们先来看一个叫做IRule的接口,这个接口有很多实现类,我们一开如果不知该该怎么自定义去写,就先看看实现类里是怎么写的。
可以看到在IRule下有很多的实现类,挑几种出来看看
·RoundRobinRule : 轮询算法
·RandomRule : 随机算法
·AvailabilityFilteringRule : 会先过滤掉 跳闸 访问故障 的服务,对剩下的进行轮询~
·RetryRule : 会先按照轮询获取服务~ 如果服务获取失败,则会在指定的时间内进行重试
好了那我们来自己写一个自定义的负载均衡算法:
首先在hkl文件夹下创建一个myrule文件夹,
在该文件夹下创建一个 HklRule.java 文件,【注意】不要和启动类放在同一级目录下,因为放在同级目录下,在启动时就会被自动扫描到,导致所有默认的负载均衡都会被覆盖,不能起到只在某些服务上使用自定义算法的作用。
那假如我们想定义一个算法:每个服务器访问5次然后就换到下一个服务器,这样轮回的遍历使用。
当然所有的代码自己写还不太现实,所以我把RandomRule随机算法拿过来改了一下
HKLRule.java
package com.hkl.myrule;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
public class HklRule extends AbstractLoadBalancerRule {
public HklRule() {
}
private int total = 0; //被调用的次数
private int currentIndex = 0; //当前是谁在提供服务
@SuppressWarnings({"RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE"})
public Server choose(ILoadBalancer lb, Object key) {
if (lb == null) {
return null;
} else {
Server server = null;
while(server == null) {
if (Thread.interrupted()) {
return null;
}
List<Server> upList = lb.getReachableServers();//获得活着的服务
List<Server> allList = lb.getAllServers();//获得全部的服务
int serverCount = allList.size();
if (serverCount == 0) {
return null;
}
// int index = this.chooseRandomInt(serverCount);
// server = (Server)upList.get(index);
//==========================================================================修改部分如下
if(total<5) {
server = upList.get(currentIndex);
total++;
}else {
total = 0;
currentIndex++;
if(currentIndex>=upList.size()) {
currentIndex = 0;
}
server = upList.get(currentIndex); //从活着得服务中,获取指定的服务来进行操作
}
//==========================================================================修改部分如上
if (server == null) {
Thread.yield();
} else {
if (server.isAlive()) {
return server;
}
server = null;
Thread.yield();
}
}
return server;
}
}
protected int chooseRandomInt(int serverCount) {
return ThreadLocalRandom.current().nextInt(serverCount);
}
public Server choose(Object key) {
return this.choose(this.getLoadBalancer(), key);
}
public void initWithNiwsConfig(IClientConfig clientConfig) {
}
}
然后在启动类加上这个扫描注解:
@RibbonClient(name = "SPRINGCLOUD-PROVIDER-DEPT",configuration = HklRule.class)
name代表的是服务在注册中心的名字,configuration是自定义rule的类
当然在实际的工作中不可能这么简单,这里主要学习一下自定义负载均衡算法的思想就好