Spring Cloud自定义粘性会话负载均衡器健康检查不生效问题
问题根因与修复方案
问题产生原因
- 自定义
ServiceInstanceListSupplier未被正确识别:CustomLoadBalancerConfiguration中定义的供应商Bean名称为discoveryClientServiceInstanceListSupplier,而Spring Cloud LoadBalancer 绑定到负载均衡器的默认Bean名称为serviceInstanceListSupplier,导致声明的带健康检查的供应商没有被注入到StickySessionLoadBalancer中,负载均衡器只能读取到空服务列表。 - 静态服务实例配置不完整:仅为
SimpleDiscoveryClient配置uri字段,健康检查组件拼接健康检查路径时,无法稳定提取实例的host、port、schema信息,导致健康检查请求构造失败,所有实例被标记为不可用。 - 配置优先级冲突:同时在yml中配置
spring.cloud.loadbalancer.configurations: health-check和自定义配置类中的ServiceInstanceListSupplier,两者逻辑冲突,默认自动装配的健康检查逻辑被自定义配置覆盖,且自定义配置未完成正确装配。
解决方案
步骤1:修正自定义负载均衡配置类
调整CustomLoadBalancerConfiguration中的Bean定义,修正供应商Bean名称并添加优先级注解,确保静态服务列表被正确加载:
public class CustomLoadBalancerConfiguration { @Bean ReactorLoadBalancer<ServiceInstance> stickySessionLoadBalancer(Environment environment, LoadBalancerClientFactory loadBalancerClientFactory) { String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME); return new StickySessionLoadBalancer(loadBalancerClientFactory .getLazyProvider(name, ServiceInstanceListSupplier.class), name); } // 修正Bean名称为serviceInstanceListSupplier,添加@Primary避免和全局配置冲突 @Bean @Primary public ServiceInstanceListSupplier serviceInstanceListSupplier(ConfigurableApplicationContext context) { return ServiceInstanceListSupplier.builder() // 指定优先使用SimpleDiscoveryClient加载静态服务列表 .withBase(new SimpleDiscoveryClientServiceInstanceListSupplier(context.getEnvironment())) .withHealthChecks() .build(context); } }
步骤2:调整yml配置
完善静态服务实例字段,移除冲突的全局负载均衡配置:
spring: application: name: sample cloud: discovery: client: health-indicator: enabled: false simple: instances: testservice: # 补充完整实例字段,避免uri解析异常 - host: localhost port: 8081 scheme: http - host: localhost port: 8082 scheme: http loadbalancer: # 移除全局health-check配置,避免和自定义配置重复装饰 cache: enabled: false health-check: path: default: /actuator/health interval: 10000 gateway: routes: - id: testrouting uri: lb://testservice predicates: - Method=GET,POST - Path=/user/**
步骤3:验证下游服务健康端点可用性
确保下游服务的/actuator/health端点可以正常访问,返回HTTP 200状态码,否则会被负载均衡器标记为不可用。
内容的提问来源于stack exchange,提问作者neelima john
相关产品推荐
相关产品推荐

