如何避免用负载均衡RestTemplate调用Eureka注册的DR状态服务实例
解决方案
针对Spring Boot 2.7.x版本,可通过给DR实例添加元数据标识+自定义负载均衡实例过滤规则的方式排除DR实例,无需硬编码IP,具体步骤如下:
1. 给服务B的DR实例添加元数据标记
在服务B的DR实例配置文件(application.yml或application.properties)中,添加Eureka元数据标识,用于区分DR实例和主实例:
eureka: instance: metadata-map: dr-instance: "true"
主实例无需配置该参数,或设置为dr-instance: "false"。
2. 自定义负载均衡实例过滤器
创建自定义过滤器类,过滤掉带有DR标识的服务实例:
import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.loadbalancer.core.DelegatingServiceInstanceListSupplier; import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier; import reactor.core.publisher.Flux; import java.util.List; import java.util.stream.Collectors; public class DrInstanceExclusionFilter { public static ServiceInstanceListSupplier filterDrInstances(ServiceInstanceListSupplier supplier) { return new DelegatingServiceInstanceListSupplier(supplier) { @Override public Flux<List<ServiceInstance>> get() { return delegate.get().map(instances -> instances.stream() // 过滤掉元数据中dr-instance为true的实例 .filter(instance -> !"true".equals(instance.getMetadata().get("dr-instance"))) .collect(Collectors.toList())); } }; } }
3. 配置服务B的负载均衡规则
创建专属配置类,将自定义过滤器应用到服务B的负载均衡逻辑中(注意:该配置类不要放在启动类的扫描包下,避免全局生效):
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier; import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.env.Environment; @Configuration public class ServiceBLoadBalancerConfig { @Bean public ServiceInstanceListSupplier serviceInstanceListSupplier(Environment environment, LoadBalancerClientFactory loadBalancerClientFactory) { ServiceInstanceListSupplier defaultSupplier = loadBalancerClientFactory.getLazyProvider(environment, ServiceInstanceListSupplier.class); return DrInstanceExclusionFilter.filterDrInstances(defaultSupplier); } }
4. 绑定服务B与自定义配置
在服务A的启动类上,通过@LoadBalancerClients注解指定服务B使用上述自定义配置:
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClients; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication @LoadBalancerClients(value = { @LoadBalancerClient(name = "service-b", configuration = ServiceBLoadBalancerConfig.class) }) public class ServiceAApplication { public static void main(String[] args) { SpringApplication.run(ServiceAApplication.class, args); } }
原理说明
服务B的DR实例注册到Eureka时会携带dr-instance=true的元数据,服务A的负载均衡组件在选择实例前,会通过自定义过滤器过滤掉带有该标识的实例,从而避免请求被转发到DR实例。当DR与主实例切换时,只需确保新实例的元数据配置正确,就能自动适配,无需修改服务A的代码或配置。
内容的提问来源于stack exchange,提问作者krishna thota
相关产品推荐
相关产品推荐

