九、自定义Ribbon负载均衡算法
1.须知
- 负载均衡有一个核心的接口实现 IRule
- AvailabilityFilteringRule会先过滤掉,跳闸(崩溃),访问故障的服务,对剩下的进行轮询
- RoundRobinRule 轮询
- RandomRule 随机
- RetryRule 会先按照轮询获取服务,如果获取服务失败,贼会在一定的时间内进行重试
通俗的讲:Ribbon客户端的包不可以放在启动类所属包下,因为与启动类同级会被扫描就会导致…!
2.新建MyRule类
在 80客户端的com.buba下建立新的myRule包,在此包下新建类,
结构如图:
添加@Configuration注解,尝试原有的随机算法
注意!
这里的方法名与类名最好不要相同!
package com.buba.myRule;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyRule {
@Bean
public IRule myRuleAAA(){
return new RandomRule();
}
}
3.在启动类上添加RibbonClient注解
//在微服务启动的时候就能去加载我们自定义的Ribbon类
@RibbonClient(name = "SPRINGCLOUD-PROVIDER-DEPT",configuration = MyRule.class)
public class DeptConsumer_80 {
public static void main(String[] args) {
SpringApplication.run(DeptConsumer_80.class);
}
}
4.测试
测试成功,可以看到从原的轮询算法变成了随机算法
5.开始自定义算法
在myRule文件下新建MyRandomRule类
package com.buba.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 MyRandomRule extends AbstractLoadBalancerRule {
//每个服务访问五次换下一个服务
//total=0,默认total=0 如果等于5 我们只想下一个服务节点
//index=0,默认等于0,如果total=5,index+1
private int total=0; //被调用的次数
private int currentIndex = 0;//当前是谁在调用服务`
//@edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE")
public Server choose(ILoadBalancer lb, Object key) {
if (lb == null) {
return null;
}
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 = chooseRandomInt(serverCount);//生成区间随机数
//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();
continue;
}
if (server.isAlive()) {
return (server);
}
server = null;
Thread.yield();
}
return server;
}
protected int chooseRandomInt(int serverCount) {
return ThreadLocalRandom.current().nextInt(serverCount);
}
@Override
public Server choose(Object key) {
return choose(getLoadBalancer(), key);
}
@Override
public void initWithNiwsConfig(IClientConfig clientConfig) {
// TODO Auto-generated method stub
}
}
6.修改刚才的MyRule
默认是轮询 现在我们自定义为MyRandomRule
package com.buba.myRule;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyRule {
@Bean
public IRule myRule(){
return new MyRandomRule();//默认是轮询 现在我们自定义为MyRandomRule
}
}
7.测试
- 可以看到,由之前的算法变成了我们自定义的算法
- 每一个服务提供者走五次 依次循环
- 测试成功
8.总结
- 这一章的前提是Ribbon已经开启了
- 这是在我的config下的ConfigBean类中使用@LoadBalanced开启了Ribbon!!!
package com.buba.springcloud.config; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; @Configuration public class ConfigBean { //@Configuration相当于springapplicationContext.xml //配置负载均衡实现RestTemplate @Bean @LoadBalanced //Ribbon public RestTemplate getrestTemplate(){ return new RestTemplate(); } }