目录

LoadBalancer完整学习笔记简介原理与自定义

LoadBalancer完整学习笔记:简介、原理与自定义

一、LoadBalancer简介

Spring Cloud LoadBalancer是Spring Cloud中负责客户端负载均衡的模块,其主要原理是通过选择合适的服务实例来实现负载均衡。

客户端负载均衡:就是负载均衡算法由客户端提供

如下图所示:
https://i-blog.csdnimg.cn/direct/5894712bc3e94159aeb00c64933224df.png

二、LoadBalancer原理

Spring Cloud LoadBalancer的底层采用了一个拦截器【LoadBalancerInterceptor】,拦截了RestTemplate发出的请求,对地址做了修改。用一幅图来总结一下:
https://i-blog.csdnimg.cn/direct/4105d6efb590424aa936a3150fc0bf5c.png

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

核心源码如下所示:

https://i-blog.csdnimg.cn/direct/e2f74d8a1d3d4a3f9ba2c066b0eaef69.png

可以看到这里的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.loadBalancerBlockingLoadBalancerClient类型,我们继续跟入。

BlockingLoadBalancerClient

核心源码如下所示:

https://i-blog.csdnimg.cn/direct/ae305bc35628479f97bff3681225b02f.png

ReactiveLoadBalancer.Factory的getInstance方法做了两件事情:

1、获取了一个具体的负载均衡算法对象

2、根据服务的id从Nacos注册中心中获取服务地址列表

紧跟着调用了RoundRobinLoadBalancer#choose方法,从服务列表中选择一个服务实例对象。

默认的负载均衡算法:RoundRobinLoadBalancer

2、详细解释

  1. 请求拦截

在调用远程服务时,请求会被 LoadBalancerInterceptor 拦截。拦截器会解析请求的目标 URI,并提取服务名:

final URI originalUri = request.getURI(); 
// 例如:http://spzx-cloud-user/api/user/findUserByUserId/1

String serviceName = originalUri.getHost();  
// 得到服务名spzx-cloud-user

此时,还没有确定具体的实例(IP:PORT),仅仅拿到了服务名。


  1. BlockingLoadBalancerClient 执行逻辑

接下来,请求会进入 BlockingLoadBalancerClientexecute 方法。核心流程如下:

ServiceInstance serviceInstance = choose(serviceId, lbRequest);

choose() 方法负责从负载均衡器中获取一个合适的服务实例。


  1. choose() 选择实例流程
ReactiveLoadBalancer<ServiceInstance> loadBalancer = 
        loadBalancerClientFactory.getInstance(serviceId);  
// 获取对应服务的负载均衡器对象,默认是 RoundRobinLoadBalancer

Response<ServiceInstance> loadBalancerResponse = 
        Mono.from(loadBalancer.choose(request)).block(); 
// 通过负载均衡算法选择一个具体的服务实例

至此,就从 服务名 转换成了 具体的 ServiceInstance (ip:port),然后请求才会真正发出去。


  1. 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
     */
    @Bean
    ReactorLoadBalancer<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://i-blog.csdnimg.cn/direct/e040b52bb6e840bab466ba3e8dc76801.png

四、Spring 项目版本管理的常见规范用语

  1. GA
  • General Availability,正式发布版。
  • 代表这个版本是稳定的,可以在生产环境使用。
  • 举例:2024.0.2 GA 就是 Spring Cloud 官方正式发布的 2024.0.2 版本。

  1. SNAPSHOT
  • 开发快照版。
  • 意思是“开发过程中的临时构建”,代码随时可能变化。
  • 每次构建都会自动更新同一个版本号的快照包(比如 2024.0.3-SNAPSHOT),所以依赖这个版本会在构建时拉到最新的构建结果。
  • 只用于开发调试,不推荐线上用

  1. PRE / M / RC

这类属于 预发布版本

  • M(Milestone):里程碑版本,比如 2025.1.0-M2 → 表示“2025.1.0 的第二个里程碑版”。
  • RC(Release Candidate):候选发布版,进入稳定阶段,除非发现重大 bug,否则就是 GA 前的最后版本。
  • PRE 有时用来泛指预发布(Pre-release),也可能是里程碑/候选版的统称。

  1. 你的例子解释
  • 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 = 预发布版(测试新功能用,不推荐生产)。