1、什么是 Ribbon
Spring Cloud Ribbon是基于Netflix Ribbon 实现的一套客户端的负载均衡工具,Ribbon 客户端组件提供一系列的完善的配置,如超时、重试等。通过Load Balancer(LB)获取到服务提供的所有机器实例,Ribbon会自动基于某种规则(轮询、随机等)去调用这些服务。 Ribbon也可以实现我们自己的负载均衡算法。
客户端负载均衡:就是进程内的LB,他是一个类库集成到消费端,通过消费端进行获取提供者的地址。
服务端负载均衡:请求调用负载均衡器,由负载均衡器进行算法解析决定调用哪一个服务。
2、Ribbon 使用
首先Eureka Client 会从 Eureka Server 拉取服务列表缓存到本地,然后Ribbon 会从 Eureka Client 的本地缓存中复制一份到自己的缓存区。然后通过 LoadBalancerInterceptor 拦截器会将服务名替换为真实的 IP:PORT ,再通过LoadBalancerClient 使用Http 方式进行接口调用。
2.1 Ribbon 快速集成
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!--添加ribbon的依赖, eureka client启动器已经依赖了ribbon,可以不配-->
<!--<dependency>-->
<!--<groupId>org.springframework.cloud</groupId>-->
<!--<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>-->
<!--</dependency>-->
添加@LoadBalanced注解
@Configuration
public class AppConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
2.2 Ribbon负载均衡策略
RandomRule: 随机选择一个Server。
RetryRule: 对选定的负载均衡策略机上重试机制,在一个配置时间段内当选择 Server不成功,则一直尝试使用subRule的方式选择一个可用的server。
RoundRobinRule: 轮询选择, 轮询index,选择index对应位置的Server。
AvailabilityFilteringRule: 过滤掉一直连接失败的被标记为circuit tripped的 后端Server,并过滤掉那些高并发的后端Server或者使用一个AvailabilityPredicate 来包含过滤server的逻辑,其实就是检查status里记录的各个Server的运行状态。
BestAvailableRule: 选择一个最小的并发请求的Server,逐个考察Server,如 果Server被tripped了,则跳过。
WeightedResponseTimeRule: 根据响应时间加权,响应时间越长,权重越 小,被选中的可能性越低。
ZoneAvoidanceRule: 复合判断Server所在区域的性能和Server的可用性选择 Server。
2.3 修改默认负载均衡策略
方式一:自定义@Bean
@Configuration
public class AppConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
@Bean
public IRule myRule() {
return new RandomRule();
}
}
方式二:添加配置
# 使用<clientName>.ribbon.<key>=<value>的形式进行配置
# 参考org.springframework.cloud.netflix.ribbon.PropertiesFactory
service-order.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule
2.4 自定义均衡算法
可以通过实现 IRule 接口或继承 AbstractLoadBalancerRule 抽象类的方式自定义负载均衡算法。
示例:
public class MyRandomRule extends AbstractLoadBalancerRule {
/** 总共被调用的次数,目前要求每台被调用5次 */
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();