Ribbon核心组件IRule
IRule:根据特定算法中从服务列表中选取一个要访问的服务
IRule中的均衡算法:
RoundRobinRule 轮询
RandomRule 随机
AvailabilityFilteringRule 会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,
还有并发的连接数量超过阈值的服务,然后对剩余的服务列表按照轮询策略进行访问
WeightedResponseTimeRule 根据平均响应时间计算所有服务的权重,响应时间越快服务权重越大被选中的概率越高。
刚启动时如果统计信息不足,则使用RoundRobinRule策略,等统计信息足够,
会切换到WeightedResponseTimeRule
RetryRule 先按照RoundRobinRule的策略获取服务,如果获取服务失败则在指定时间内会进行重 试,获取可用的服务
BestAvailableRule 会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的 服务
ZoneAvoidanceRule 默认规则,复合判断server所在区域的性能和server的可用性选择服务器
IRule中负载均衡的使用规则是:如果没有在配置类显示声明,就默认使用 RoundRobinRule 轮询负载均衡算法
如何显示声明算法:
在configBean 中 做如下配置:
@Bean
public IRule myRule() {
return new RetryRule();//用我们重新选择的随机算法替代默认的轮询。
}
自定义配置:
在启动该微服务的时候就能去加载我们的自定义Ribbon配置类,从而使配置生效,形如:
@RibbonClient(name="MICROSERVICECLOUD-DEPT",configuration=MySelfRule.class)
在启动类之上新建一个包myrule ,然后新建一个MySelfRule类
package cn.blogsx.myrule;
/**
* @author Alex
* @create 2020-02-23 15:53
**/
public class MySelfRule {
@Bean
public IRule myRule() {
return new RandomRule();
}
}
此时仍然为 系统已有随机算法,不过已经可以在此基础上修改了。
在MySelfRule类同一包下,新建一个CustomRandomRule 自定义随机规则类,并实现想要的算法:
依旧轮询策略,但是加上新需求,每个服务器要求被调用5次。也即
以前是每台机器一次,现在是每台机器5次
package cn.blogsx.myrule;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;
import org.springframework.context.annotation.Configuration;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
/**
* @author Alex
* @create 2020-02-23 19:37
**/
@Configuration
public class CustomRandomRule extends AbstractLoadBalancerRule {
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) {
return null;
}
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;
}
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 iClientConfig) {
}
}
如此进行测试即可看到每台实例被连续访问5次,且5次后自动轮询修改服务实例