这里的负载均衡使用,基于RestTemplate。Fegin的负载均衡策略最终也是对其的包装
Ribbon负载均衡-已不在默认集成
服务发现远程调用时地址是服务名, 这个地址是不能真正访问的. 而这解析的过程就是ribbon在起作用
RestTemplate使用
通过给RestTemplate bean添加注解@LoadBalanced实现
这个注解是让类LoadBalancerInterceptor生效,实现拦截处理
特别说明
新版本的spring cloud 移除了对ribbon的支持,众所周知,netflix以及停止维护了,所有新版本的spring cloud移除了eureka的其他组件。
目前默认使用的是LoadBalancer
LoadBalancer
从springcloud2020版本开始默认移除了对Ribbon的依赖,官方默认推荐使用Spring Cloud Loadbalancer正式替换Ribbon,并成为了Spring Cloud负载均衡器的唯一实现。
启动方式和核心和ribbon一样。通过注解启动,和类LoadBalancerInterceptor生效。
不过对于LoadBalancerClient在Spring Cloud LoadBalancer中实现类则是BlockingLoadBalancerClient
对于负载均衡的核心类为ReactorServiceInstanceLoadBalancer
1、默认负载均衡策略
默认实现了如下两种负载均衡策略:
RandomLoadBalancer - 随机分配策略
(默认) RoundRobinLoadBalancer - 轮询分配策略
2、自定义负载均衡策略
通过ReactorServiceInstanceLoadBalancer的execute方法可知通过choose方法获取到真正调用的实例
choose通过loadBalancerClientFactory获取到serviceId对应到负载均衡策略。再通过具体的负载均衡策略获取到服务实例。默认的loadBalancerClientFactory是LoadBalancerClientFactory
loadBalancerClientFactory是springFactory的形式获取bean。每次通过serviceId获取对应的一个context。通过这个context获取符合要求的负载均衡策略。这里是ReactorServiceInstanceLoadBalancer接口类型的bean。
另外在图一中的getSupportedLifecycleProcessors中也会从这个context获取LoadBalancerLifecycle接口的bean,从而实现在负载平衡之前和之后执行的操作。
第一次通过serviceId获取时,对应的context都是不存在的。在创建时会获取serviceId对应配置的configuration,并向这个spring上下文中注册该配置,从而生效预先注册的bean。
每个serviceId对应的configuration是一个NamedContextFactory.Specification的接口,其有两个方法如下图, 默认实现是LoadBalancerClientSpecification
public interface Specification {
// 对应serviceID
String getName();
// 注册给spring的bean
Class<?>[] getConfiguration();
}
方式一
所以如果要自定义一个负载均衡策略,先要注册一个serviceId对应的NamedContextFactory.Specification。在这个configuration中添加ReactorServiceInstanceLoadBalancer接口的自定义负载均衡策略
/**
* @author cyp
* @date 2023-08-20
*/
@Configuration
public class MyRemoteServiceLoadBalancerConfiguration {
@Bean("remoteService-userService")
public LoadBalancerClientSpecification myLoadBalancer(){
LoadBalancerClientSpecification myLoadBalancer = new LoadBalancerClientSpecification();
myLoadBalancer.setName("user-service");
myLoadBalancer.setConfiguration(new Class[]{CustomRandomLoadBalancerClient.class});
return myLoadBalancer;
}
}
方式二
不直接给自定义的负载均衡策略,而是加载Configuration。例如加载nacos的配置
@Bean("remoteService-userService")
public LoadBalancerClientSpecification myLoadBalancer(){
return new LoadBalancerClientSpecification("user-service", new Class[]{NacosLoadBalancerClientConfiguration.class});
}
方式三
在启动类,使用@LoadBalancerClient或者@LoadBalancerClients注解,加载自己的配置类,由此切换loadBalancer默认的负载均衡策略.
而通过@LoadBalancerClients的defaultConfiguration 可以全局修改
@LoadBalancerClients(defaultConfiguration = NacosLoadBalancerClientConfiguration.class)