SpringCloud-Alibaba学习(四):Ribbon负载均衡
Ribbon负载均衡
1、简介
Ribbon
是 Netflix 公司开源的一个负载均衡的项目,是客户端负载均衡器,运行在客户端上。
用于解决服务实例列表在调用时的负载均衡的问题。
2、Ribbon 使用
前篇 nacos 实例中有相关集成:https://www.cnblogs.com/liuyiyuan/p/16421731.html#325-远程调用
第一步:pom 依赖
SpringCloud 已经依赖了 Ribbon
第二步:@LoadBalance 注解
通过 Spring Cloud 原生注解 @EnableDiscoveryClient
开启服务注册发现,再给RestTemplate
实例添加 @LoadBalance
注解,开启与 Ribbon
的集成,代码中无感知。
@Bean @LoadBalanced // 使Ribbon生效 public RestTemplate restTemplate() { return new RestTemplate(); }
3、Ribbon 工作流程
4、Ribbon 源码了解
LoadBalancerAutoConfiguration
自动注入拦截器
进入 LoadBalancerInterceptor
@Override public ClientHttpResponse intercept(final HttpRequest request, final byte[] body, final ClientHttpRequestExecution execution) throws IOException { final URI originalUri = request.getURI(); // 从请求中获取 URI String serviceName = originalUri.getHost(); // 获取 host 作为服务名 Assert.state(serviceName != null, "Request URI does not contain a valid hostname: " + originalUri); return this.loadBalancer.execute(serviceName, this.requestFactory.createRequest(request, body, execution)); }
查看 this.loadBalancer.execute
方法
会进入 RibbonLoadBalancerClient#execute
方法
public <T> T execute(String serviceId, LoadBalancerRequest<T> request, Object hint) throws IOException { ILoadBalancer loadBalancer = getLoadBalancer(serviceId); // 获取实例列表,serviceId就是服务名 Server server = getServer(loadBalancer, hint); // 对实例列表进行负载均衡获取到一个server if (server == null) { throw new IllegalStateException("No instances available for " + serviceId); } RibbonServer ribbonServer = new RibbonServer(serviceId, server, isSecure(server, serviceId), serverIntrospector(serviceId).getMetadata(server)); return execute(serviceId, ribbonServer, request); }
方法 getLoadBalancer(serviceId)
会创建负载均衡器 ZoneAwareLoadBalancer
方法 getServer(loadBalancer, hint)
内部调用 ZoneAwareLoadBalancer#chooseServer
,再调用父类方法即BaseLoadBalancer#chooseServer
,根据负载均衡策略获取具体的 Server
5、Ribbon 的负载均衡策略
Ribbon 的负载均衡策略核心组件是 IRule,根据特定算法从服务列表中选取一个需要访问的服务;
其中 IRule 是一个接口,有七个自带的实现,可以实现不同的负载均衡策略
策略类 | 策略描述 |
---|---|
BestAvailableRule | 选择并发请求最少的server |
AvailabilityFilteringRule | 先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,以及并发连接数超过阈值的服务,然后对剩余服务进行轮询 |
WeightedResponseTimeRule | 根据平均响应时间计算服务权重,若统计信息不足则安装轮询规则,统计信息足够后按照响应时间选择服务 |
RetryRule | 正常时按照轮询选择服务,有服务出现故障时,在轮询一定次数后依然故障,则会跳过故障的服务继续轮询 |
RoundRobinRule | 轮询规则 |
RandomRule | 随机规则 |
ZoneAvoidanceRule | 默认策略,加了一些过滤条件,过滤成功后继续采用轮询方式选择服务 |
切换 Ribbon 默认的负载均衡策略
Ribbon 是客户端的负载均衡器,所以策略要配置到服务消费方上。
配置类,注意这个配置类不需要 Spring 的扫描自动注入
public class RibbonRuleConfig { @Bean public IRule rule() { return new RandomRule(); } }
启动类上添加注解,指定上面的配置类
// name为要调的微服务名称,configuration指定策略配置类 @RibbonClient(name = "ribbon-provider", configuration = RibbonRuleConfig.class)
6、缓存的定时刷新
服务消费方在第一次远程调用时,会将服务信息缓存起来,后续直接通过缓存发起调用。
如果注册中心的服务列表发生了变更,消费方如何感知呢?
ribbon 是使用了定时刷新机制。
核心代码在类 DynamicServerListLoadBalancer
中的ServerListUpdater.UpdateAction#doUpdate
定时调度是 PollingServerListUpdater#start 方法内定义了一个 Runnable 使用 ScheduledThreadPoolExecutor 进行调度,调度时间间隔是 30s
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· 单线程的Redis速度为什么快?
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码