官网指出:
这个自定义的类不能放在@ComponentScan所扫描的当前包以及子包下,否则我们自定义的这个配置类就会被所有的Ribbon客户端所共享,也就是我们达不到特殊化指定的目的了。推荐在springboot主程序扫描的包范围之外进行自定义配置类。
代码实现如下
配置类不应该在SpringBoot的包路径下,通过@RibbonClient 注解加载:
package com.dsx.rule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RetryRule;
@Configuration
public class MySelfRule {
//在这里选择负载均衡算法,
@Bean
public IRule myRule() {
return new MyRandomRule();//默认轮询,此处是自定义的算法
}
}
自定义负载均衡算法
package com.dsx.rule;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;
public class MyRandomRule extends AbstractLoadBalancerRule{
//每个服务访问5次,换下一个服务(2个)
//被调用的次数
private int total=0;
//当前是谁在调用服务
private int currentIndex = 0;
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;
}
//自定义算法
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
}
}
启动类
package com.dsx;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import com.dsx.rule.MySelfRule;
@EnableEurekaClient //向服务注册中心进行注册
@SpringBootApplication
@RibbonClient(name="MICROSERVICE-PRODUCT",configuration=MySelfRule.class)
public class ConsumerApp {
public static void main(String[] args) {
SpringApplication.run(ConsumerApp.class, args);
}
}
启动后访问实现了简单的自定义的负载均衡算法。
注意:
@RibbonClient(name = "MICROSERVICE-PRODUCT", configuration = MySelfRule.class)
name指定针对哪个服务 进行负载均衡,而configuration指定负载均衡的算法具体实现类
自定义Ribbon Client的主要作用就是使用自定义配置替代Ribbon默认的负载均衡策略,