SpringCloud的Ribbon自定义负载均衡算法
1.Ribbon默认使用RoundRobinRule策略轮询选择server
策略名 | 策略声明 | 策略描述 | 实现说明 |
BestAvailableRule | public class BestAvailableRule extends ClientConfigEnabledRoundRobinRule |
选择一个最小的并发请求的server | 逐个考察Server,如果Server被tripped了,则忽略,在选择其中ActiveRequestsCount最小的server |
AvailabilityFilteringRule | public class AvailabilityFilteringRule extends PredicateBasedRule | 过滤掉那些因为一直连接失败的被标记为circuit tripped的后端server,并过滤掉那些高并发的的后端server(active connections 超过配置的阈值) | 使用一个AvailabilityPredicate来包含过滤server的逻辑,其实就就是检查status里记录的各个server的运行状态 |
WeightedResponseTimeRule | public class WeightedResponseTimeRule extends RoundRobinRule | 根据响应时间分配一个weight,响应时间越长,weight越小,被选中的可能性越低。 | 一个后台线程定期的从status里面读取评价响应时间,为每个server计算一个weight。Weight的计算也比较简单responsetime 减去每个server自己平均的responsetime是server的权重。当刚开始运行,没有形成status时,使用roubine策略选择server。 |
RetryRule | public class RetryRule extends AbstractLoadBalancerRule | 对选定的负载均衡策略机上重试机制 | 在一个配置时间段内当选择server不成功,则一直尝试使用subRule的方式选择一个可用的server |
RoundRobinRule | public class RoundRobinRule extends AbstractLoadBalancerRule | roundRobin方式轮询选择server | 轮询index,选择index对应位置的server |
RandomRule | public class RandomRule extends AbstractLoadBalancerRule |
随机选择一个server |
在index上随机,选择index对应位置的server |
ZoneAvoidanceRule |
public class ZoneAvoidanceRule extends PredicateBasedRule |
复合判断server所在区域的性能和server的可用性选择server |
使用ZoneAvoidancePredicate和AvailabilityPredicate来判断是否选择某个server,前一个判断判定一个zone的运行性能是否可用,剔除不可用的zone(的所有server),AvailabilityPredicate用于过滤掉连接数过多的Server。 |
切换策略
-
-
public class ConfigBean {
-
-
// @Bean
-
// public RestTemplate getRestTemplate() {
-
// return new RestTemplate();
-
// }
-
-
-
-
public RestTemplate getRestTemplate() {
-
return new RestTemplate();
-
}
-
-
-
public IRule myRule()
-
{
-
//return new RoundRobinRule();
-
// return new RandomRule();//达到的目的,用我们重新选择的随机算法替代默认的轮询。
-
return new RetryRule();
-
}
-
}
自定义算法:
配置类(必须不能在启动类和启动类下所包含的子包下面)
-
public class RandomRule_ZY extends AbstractLoadBalancerRule
-
{
-
-
// total = 0 // 当total==5以后,我们指针才能往下走,
-
// index = 0 // 当前对外提供服务的服务器地址,
-
// total需要重新置为零,但是已经达到过一个5次,我们的index = 1
-
// 分析:我们5次,但是微服务只有8001 8002 8003 三台,OK?
-
//
-
-
-
private int total = 0; // 总共被调用的次数,目前要求每台被调用5次
-
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) {
-
/*
-
* No servers. End regardless of pass, because subsequent passes only get more
-
* restrictive.
-
*/
-
return null;
-
}
-
-
// int index = rand.nextInt(serverCount);// java.util.Random().nextInt(3);
-
// server = upList.get(index);
-
-
-
// private int total = 0; // 总共被调用的次数,目前要求每台被调用5次
-
// private int currentIndex = 0; // 当前提供服务的机器号
-
if(total < 5)
-
{
-
server = upList.get(currentIndex);
-
total++;
-
}else {
-
total = 0;
-
currentIndex++;
-
if(currentIndex >= upList.size())
-
{
-
currentIndex = 0;
-
}
-
}
-
-
-
if (server == null) {
-
/*
-
* The only time this should happen is if the server list were somehow trimmed.
-
* This is a transient condition. Retry after yielding.
-
*/
-
Thread.yield();
-
continue;
-
}
-
-
if (server.isAlive()) {
-
return (server);
-
}
-
-
// Shouldn't actually happen.. but must be transient or a bug.
-
server = null;
-
Thread.yield();
-
}
-
-
return server;
-
-
}
-
-
-
public Server choose(Object key)
-
{
-
return choose(getLoadBalancer(), key);
-
}
-
-
-
public void initWithNiwsConfig(IClientConfig clientConfig)
-
{
-
// TODO Auto-generated method stub
-
-
}
-
-
}
-
-
public class MySelfRule {
-
-
public IRule myRule() {
-
// return new RandomRule();// Ribbon默认是轮询,我自定义为随机
-
return new RandomRule_ZY();// 我自定义为每台机器5次
-
}
-
}
另一配置类(在启动类包里面)
-
-
public class ConfigBean {
-
-
// @Bean
-
// public RestTemplate getRestTemplate() {
-
// return new RestTemplate();
-
// }
-
-
-
-
public RestTemplate getRestTemplate() {
-
return new RestTemplate();
-
}
-
-
// @Bean
-
// public IRule myRule()
-
// {
-
// //return new RoundRobinRule();
-
// return new RandomRule();//达到的目的,用我们重新选择的随机算法替代默认的轮询。
-
// return new RetryRule();
-
// }
-
}
启动类
-
-
-
//在启动该微服务的时候就能去加载我们的自定义Ribbon配置类,从而使配置生效
-
//@RibbonClient(name="MICROSERVICECLOUD-DEPT",configuration=MySelfRule.class)
-
-
public class DeptConsumer80_App {
-
public static void main(String[] args) {
-
SpringApplication.run(DeptConsumer80_App.class, args);
-
}
-
}
测试效果为每个server执行5次再轮询
转自:https://blog.csdn.net/flynn_chen/article/details/80631717