LoadBalancer完整学习笔记:简介、原理与自定义
目录
- 一、LoadBalancer简介
- 二、LoadBalancer原理
- 1、源码跟踪
- 2、详细解释
- 3、更改负载均衡算法
- 三、官网自定义负载均衡算法例子
- 四、Spring 项目版本管理的常见规范用语
一、LoadBalancer简介
Spring Cloud LoadBalancer是Spring Cloud中负责客户端负载均衡的模块,其主要原理是通过选择合适的服务实例来实现负载均衡。
客户端负载均衡:就是负载均衡算法由客户端提供
如下图所示:
二、LoadBalancer原理
Spring Cloud LoadBalancer的底层采用了一个拦截器【LoadBalancerInterceptor】,拦截了RestTemplate发出的请求,对地址做了修改。用一幅图来总结一下:
执行流程说明:
1、通过LoadBalancerInterceptor请求拦截器拦截我们的RestTemplate请求:http://spzx-cloud-user/api/user/findUserByUserId/1
2、获取请求的url,然后从请求的url中获取服务提供方的主机名称
3、然后调用LoadBalancerClient中的execute方法,将服务提供方的名称传递过去
4、在LoadBalancerClient的choose方法中通过ReactiveLoadBalancer.Factory从Nacos注册中心中获取服务列表以及负载均衡算法实例对象
5、通过ReactiveLoadBalancer从服务列表中选择一个服务实例地址,然后发起远程调用
1、源码跟踪
LoadBalancerInterceptor
核心源码如下所示:
可以看到这里的intercept方法,拦截了用户的HttpRequest请求,然后做了几件事:
1、request.getURI()
:获取请求uri,本例中就是 http://spzx-cloud-user/api/user/findUserByUserId/2
2、originalUri.getHost()
:获取uri路径的主机名,其实就是服务id,spzx-cloud-user
3、this.loadBalancer.execute()
:处理服务id,和用户请求。
这里的this.loadBalancer
是BlockingLoadBalancerClient
类型,我们继续跟入。
BlockingLoadBalancerClient
核心源码如下所示:
ReactiveLoadBalancer.Factory的getInstance方法做了两件事情:
1、获取了一个具体的负载均衡算法对象
2、根据服务的id从Nacos注册中心中获取服务地址列表
紧跟着调用了RoundRobinLoadBalancer#choose方法,从服务列表中选择一个服务实例对象。
默认的负载均衡算法:RoundRobinLoadBalancer
2、详细解释
- 请求拦截
在调用远程服务时,请求会被 LoadBalancerInterceptor 拦截。拦截器会解析请求的目标 URI,并提取服务名:
final URI originalUri = request.getURI();
// 例如:http://spzx-cloud-user/api/user/findUserByUserId/1String serviceName = originalUri.getHost();
// 得到服务名:spzx-cloud-user
此时,还没有确定具体的实例(IP:PORT),仅仅拿到了服务名。
- BlockingLoadBalancerClient 执行逻辑
接下来,请求会进入 BlockingLoadBalancerClient 的 execute
方法。核心流程如下:
ServiceInstance serviceInstance = choose(serviceId, lbRequest);
choose()
方法负责从负载均衡器中获取一个合适的服务实例。
- choose() 选择实例流程
ReactiveLoadBalancer<ServiceInstance> loadBalancer = loadBalancerClientFactory.getInstance(serviceId);
// 获取对应服务的负载均衡器对象,默认是 RoundRobinLoadBalancerResponse<ServiceInstance> loadBalancerResponse = Mono.from(loadBalancer.choose(request)).block();
// 通过负载均衡算法,选择一个具体的服务实例
至此,就从 服务名 转换成了 具体的 ServiceInstance (ip:port),然后请求才会真正发出去。
- ReactiveLoadBalancer 接口实现
Spring Cloud LoadBalancer 定义了 ReactiveLoadBalancer
接口,不同的实现类代表不同的负载均衡策略:
-
RoundRobinLoadBalancer(默认,轮询):依次选择服务实例。
org.springframework.cloud.loadbalancer.core.RoundRobinLoadBalancer
-
RandomLoadBalancer(随机):随机选择一个实例。
org.springframework.cloud.loadbalancer.core.RandomLoadBalancer
-
NacosLoadBalancer(Nacos 扩展,随机 + 就近机房优先):
当使用 Nacos 注册中心,并启用以下配置时,会优先选择同集群的实例。spring:cloud:loadbalancer:nacos:enabled: true
对应实现类:
com.alibaba.cloud.nacos.loadbalancer.NacosLoadBalancer
3、更改负载均衡算法
LoadBalancer默认的负载均衡算法是RoundRobinLoadBalancer,如果想更改默认的负载均衡算法,那么此时需要向Spring容器中注册一个Bean,并且配置负载均衡的使用者。
代码如下所示:
1、在Spring容器中注册一个Bean
public class CustomLoadBalancerConfiguration {/*** @param environment: 用于获取环境属性配置,其中LoadBalancerClientFactory.PROPERTY_NAME表示该负载均衡器要应用的服务名称。* @param loadBalancerClientFactory: 是Spring Cloud中用于创建负载均衡器的工厂类,通过getLazyProvider方法获取ServiceInstanceListSupplier对象,以提供可用的服务列表。* ServiceInstanceListSupplier:用于提供ServiceInstance列表的接口,可以从DiscoveryClient或者其他注册中心中获取可用的服务实例列表。* @return*/@BeanReactorLoadBalancer<ServiceInstance> randomLoadBalancer(Environment environment, LoadBalancerClientFactory loadBalancerClientFactory) {String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);return new RandomLoadBalancer(loadBalancerClientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class), name);}
}
2、配置负载均衡算法的使用者
@Configuration
@LoadBalancerClients(value = {@LoadBalancerClient(name = "spzx-cloud-user" , configuration = CustomLoadBalancerConfiguration.class) // 将负载均衡算法应用到指定的服务提供方中
})
public class RestTemplateConfiguration {@Bean@LoadBalanced // 让RestTemplate具有负载均衡的能力public RestTemplate restTemplate() {return new RestTemplate() ;}}
三、官网自定义负载均衡算法例子
https://spring.io/projects/spring-cloud#learn
四、Spring 项目版本管理的常见规范用语
- GA
- General Availability,正式发布版。
- 代表这个版本是稳定的,可以在生产环境使用。
- 举例:
2024.0.2 GA
就是 Spring Cloud 官方正式发布的 2024.0.2 版本。
- SNAPSHOT
- 开发快照版。
- 意思是“开发过程中的临时构建”,代码随时可能变化。
- 每次构建都会自动更新同一个版本号的快照包(比如
2024.0.3-SNAPSHOT
),所以依赖这个版本会在构建时拉到最新的构建结果。 - 只用于开发调试,不推荐线上用。
- PRE / M / RC
这类属于 预发布版本:
- M(Milestone):里程碑版本,比如
2025.1.0-M2
→ 表示“2025.1.0 的第二个里程碑版”。 - RC(Release Candidate):候选发布版,进入稳定阶段,除非发现重大 bug,否则就是 GA 前的最后版本。
- PRE 有时用来泛指预发布(Pre-release),也可能是里程碑/候选版的统称。
- 你的例子解释
2024.0.2 GA
→ 2024 系列的正式稳定版(推荐生产用)。2024.0.3-SNAPSHOT
→ 下一个补丁版本的快照(还在开发)。2025.0.0 CURRENT GA
→ 当前主线的稳定版。2025.1.0-M2 PRE
→ 下一个大版本的第二个里程碑预发布版。2025.1.0-SNAPSHOT
→ 开发中版本(代码随时变动)。
✅ 总结:
- GA = 正式稳定版(生产环境用这个)。
- SNAPSHOT = 开发快照(不要上生产)。
- PRE / M / RC = 预发布版(测试新功能用,不推荐生产)。