从特定算法从服务列表中选取一个要访问的服务。
Ribbon提供了多种策略:如轮询、随机、根据响应时间加权。
- RoundRobbinRule:轮询
- RandomRule:随机
- AvailavilityFilterRule:先过滤掉由于多次访问故障而处于断路器跳闸的服务,还有并发的连接数量超过阈值的服务,然后对剩余的服务列表按照轮询的策略进行访问
- WeightedResponseTimeRule:根据响应时间计算权重,响应速度越快,被选中的几率越高。
- RetryRule:先按照RoundRobinRule的策略获取服务,如果失败会重试
- BestAviailableRule:会过滤到由于多次访问故障而处于断路器处于跳闸的状态的服务,然后选择一个并发量最小的服务
- ZoneAvoidanceRule:默认规则,复合判断server所在区域的性能和server的可用性选择服务器
@Configuration
public class ConfigBean{
@Bean
@LoadBalanced // 开启负载均衡
public RestTemplate restTemplate(){
return new RestTemplate();
}
@Bean
public IRule myRule(){
return new RandomRule(); // 使用RandomRule
}
}
自定义的负载均衡机制
在启动微服务的时候就去加载我们自定义的Ribbon配置类,从而使配置生效,如:
@Ribbon(name=“xxxx”,configuration=xxxRule.class)
@SpringBootApplication
@EnableEurekaClient
@RibbonClient(name="MICROSERVICECLOUD-DEPT", configuration = MyClassRule.class)
public class MainApplication{
public static void main(String[] args) {
// 主启动类代码
// 不可以在@ComponentScan包和子包下
@Configuration
public class MyClassRule {
@Bean
public IRule myRule(){
return new MyRuleRobbin ();
}
}
// 模仿RoundRobbinRule所写的自定义规则类
public class MyRuleRobbin extends AbstractLoadBalancerRule {
// 当前Server本轮调用次数
private int total = 0;
// 当前Server的index
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;
}
// 每个Server调用5次
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;
}
@Override
public Server choose(Object key) {
return choose(getLoadBalancer(), key);
}
@Override
public void initWithNiwsConfig(IClientConfig iClientConfig) {
}
}