# 03.微服务-负载均衡
Spring Cloud LoadBalancer 是 Spring 官方推出的客户端负载均衡器,已替代 Netflix Ribbon 成为 Spring Cloud 默认负载均衡方案
# 1.负载均衡策略
# 1.1 内置策略
| 策略名称 | 实现类 | 核心原理 | 适用场景 |
|---|---|---|---|
| 轮询 | RoundRobinLoadBalancer | 按顺序轮流选择实例,通过原子计数器取模实现 | 通用场景,服务实例性能相近 |
| 随机 | RandomLoadBalancer | 从可用实例列表中随机选择 | 打散请求,避免"热点"实例 |
# 1.2 通过 ServiceInstanceListSupplier 实现的高级策略
ServiceInstanceListSupplier 是实例列表供应器,可通过链式组合实现高级负载均衡特性
| 策略类型 | 核心机制 | 适用场景 |
|---|---|---|
| 加权 | 从实例元数据读取 weight 值作为权重,权重越高被选中概率越大;未配置则默认为 1 | 实例配置异构,希望按比例分配流量 |
| 区域感知 | 优先选择与服务调用方同一区域的实例;同区域无可用实例则回退到全部实例 | 多机房/跨地域部署,降低网络延迟 |
| 健康检查 | 定期对实例执行健康检查,仅返回健康实例;无健康实例时返回全部 | 使用 SimpleDiscoveryClient 或无健康检查机制的场景 |
| 缓存 | 缓存实例列表,减少每次请求都拉取注册中心的开销 | 生产环境必开,大大提升性能 |
# 1.3 策略对比
| 对比维度 | 轮询 (RoundRobin) | 随机 (Random) | 加权 (Weighted) | 区域感知 (ZonePreference) |
|---|---|---|---|---|
| 实现复杂度 | 低 | 低 | 中 | 中 |
| 负载均衡效果 | 均匀 | 近似均匀 | 按权重不平均 | 优先同区域 |
| 是否需元数据配置 | 否 | 否 | 是(需 weight 标签) | 是(需 zone 标签) |
| 适用场景 | 通用 | 打散请求 | 异构实例 | 多机房部署 |
# 2.配置方式
# 2.1关键配置项
spring:
cloud:
loadbalancer:
# 缓存配置(生产环境推荐)
cache:
enabled: true # 开启缓存,默认 true
ttl: 35s # 缓存过期时间,默认 35s
capacity: 256 # 缓存初始容量,默认 256
# 预加载配置(避免首次请求延迟)
eager-load:
clients: # 指定服务 ID 列表
- service-a
- service-b
# 健康检查配置
health-check:
path:
default: /actuator/health # 健康检查默认路径
interval: 30s # 检查间隔
# 区域配置(区域感知时需要)
zone: cn-north-1 # 覆盖 DiscoveryClient 的区域设置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 2.2策略配置方式
random配置
public class CustomLoadBalancerConfiguration {
@Bean
ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(Environment environment,
LoadBalancerClientFactory loadBalancerClientFactory) {
String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
return new RandomLoadBalancer(loadBalancerClientFactory
.getLazyProvider(name, ServiceInstanceListSupplier.class),
name);
}
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
weight配置
public class WeightedConfig {
@Bean
public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(
ConfigurableApplicationContext context) {
return ServiceInstanceListSupplier.builder()
.withDiscoveryClient() // 从注册中心获取实例
.withWeighted() // 启用加权(可自定义权重算法)
.withCaching() // 启用缓存
.build(context);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
zone配置
public class ZonePreferenceConfig {
@Bean
public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(
ConfigurableApplicationContext context) {
return ServiceInstanceListSupplier.builder()
.withDiscoveryClient()
.withCaching()
.withZonePreference() // 启用区域感知
.build(context);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
自定义配置
public class CustomLoadBalancer implements ReactorServiceInstanceLoadBalancer {
private final String serviceId;
private final ServiceInstanceListSupplier serviceInstanceListSupplier;
public CustomLoadBalancer(ServiceInstanceListSupplier supplier, String serviceId) {
this.serviceInstanceListSupplier = supplier;
this.serviceId = serviceId;
}
//模仿RandomLoadBalancer写的
@Override
public Mono<Response<ServiceInstance>> choose(Request request) {
return serviceInstanceListSupplier.get(request)
.next()
.map(instances -> {
if (instances.isEmpty()) {
return new EmptyResponse();
}
// 自定义选择逻辑
ServiceInstance selected = customSelect(instances);
return new DefaultResponse(selected);
});
}
private ServiceInstance customSelect(List<ServiceInstance> instances) {
// 示例:优先选择带有特定元数据的实例
for (ServiceInstance instance : instances) {
if ("v2".equals(instance.getMetadata().get("version"))) {
return instance;
}
}
// 回退:选择第一个
return instances.get(0);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
注 :注意如果负载均衡策略配置类使用spring注解@ComponentScan或者@Configuration,就要注意如果被SpringBootApplication的ComponentScan扫描到(默认扫描SpringBootApplication目录下的全部包),就会变成全局的负载均衡策略,如果需要局部负载均衡最好不用注解,或者设置不被默认的ComponentScan扫描到
# 2.3使用配置
写在启动类上
@LoadBalancerClients({@LoadBalancerClient(value = "stock-service", configuration = {CustomLoadBalancerConfiguration.class})})
1
value:使用负载均衡的服务名(nacos中注册的名字)
configuration:使用哪个配置类
@LoadBalancerClients可写多个@LoadBalancerClient