SpringCloud Ribbon - 替换负载均衡规则
ribbon默认的负载均衡规则是轮询的方式,即假如一个服务A有两个服务实例A1、A2,当第一次请求时使用A1实例,第二次请求时使用A2实例,以此往复。该轮询算法也很简单:即服务器实例list,list[1] = A1, list[2] = A2。通过请求数(reqCount)取余服务实例总数(size)得到的结果(ret)作为List下标,即 reqCount%size=ret,serviceInstance = list.get(ret)。
/**
* Inspired by the implementation of {@link AtomicInteger#incrementAndGet()}.
*
* @param modulo The modulo to bound the value of the counter.
* @return The next value.
*/
private int incrementAndGetModulo(int modulo) {
for (;;) {
int current = nextServerCyclicCounter.get();
int next = (current + 1) % modulo;
if (nextServerCyclicCounter.compareAndSet(current, next))
return next;
}
}
两种方式:
方式一: 编程式
方式二: 配置式
在使用编程式替换负载均衡的规则时需要注意一下两点:
- 注意项目的结构。 如果所有负载均衡调用都使用该规则,则可以将配置规则的类(本文中的CustomRibbonRule类)放在启动类所在包的子包下。如果只有某些指定的负载均衡使用该规则,则需要将配置规则的类放在启动类所在包之外。参考本文中所给出的项目结构示意图。
- @RibbonClient注解中设置服务名字时务必小写,否则设定的替换规则不会生效而使用默认的规则。@RibbonClient(name = "a-service", configuration = CustomRibbonRule.class),笔者之前按照官方文档写的时候规则无论如何都不生效,在尝试将服务名修改为全小写后,规则生效。
项目结构示意图
编程式替换负载均衡规则有以下几个步骤:
步骤一、配置使用哪种负载均衡规则
@Configuration
public class CustomRibbonRule {
@Bean
public IRule ribbonRule() {
return new RandomRule();
}
}
使用随机规则
步骤二、启动类加上@RibbonClient注解
@SpringBootApplication
@EnableEurekaClient
@RibbonClient(name = "a-service", configuration = CustomRibbonRule.class)
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
@Bean
@LoadBalanced // LoadBalance+restTemplate实现负载均衡
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
配置式替换负载均衡规则
a-service:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
com.netflix.loadbalancer.RandomRule是所使用规则的全类名
netflix提供了如下Rule,当然也可以定制自己的规则。
ribbon替换负载均衡规则总结,仅作参考,不足之处欢迎指出。