Spring Cloud LoadBalancer服务解析失败问题排查求助
Spring Cloud LoadBalancer 服务解析失败问题排查
问题场景
按照Spring Cloud LoadBalancer指南实现客户端负载均衡,调用http://my-service/endpoint时抛出UnknownHostException,无法解析服务名。相关代码及配置如下:
Controller代码
@RestController class MyController( val loadBalancedWebClientBuilder: WebClient.Builder ) { private fun makeRequest() { loadBalancedWebClientBuilder.build().post() .uri(URI("http://my-service/endpoint")) .body(BodyInserters.fromValue("{ \"data\" = \"data\" }")) .retrieve() .bodyToMono(String::class.java) .block() } }
WebClient配置
@Configuration @LoadBalancerClient(name = "my-service", configuration = [LoadBalancerConfig::class]) class WebClientConfig { @LoadBalanced @Bean fun webClientBuilder(): WebClient.Builder { return WebClient.builder() } }
负载均衡配置
class LoadBalancerConfig { @Bean @Primary fun serviceInstanceListSupplier(): ServiceInstanceListSupplier { return ServiceInstanceListSupplerImpl("my-service") } } class ServiceInstanceListSupplerImpl(private val serviceId: String) : ServiceInstanceListSupplier { override fun getServiceId(): String { return serviceId } override fun get(): Flux<List<ServiceInstance>> { return Flux.just(listOf("http://localhost").mapIndexed { index, s - DefaultServiceInstance(index.toString(), serviceId, s, 8088, true) }) } }
配置文件
spring: cloud: discovery: client: simple: instances: my-service[0].uri: http://localhost:8088
异常信息
org.springframework.web.reactive.function.client.WebClientRequestException: Failed to resolve 'my-service' after 4 queries ; nested exception is java.net.UnknownHostException: Failed to resolve 'my-service' after 4 queries at org.springframework.web.reactive.function.client.ExchangeFunctions$DefaultExchangeFunction.lambda$wrapException$9(ExchangeFunctions.java:141) ~[spring-webflux-5.3.24.jar:5.3.24] Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: Error has been observed at the following site(s): *__checkpoint ⇢ Request to POST http://my-service/endpoint [DefaultWebClient] Original Stack Trace: at org.springframework.web.reactive.function.client.ExchangeFunctions$DefaultExchangeFunction.lambda$wrapException$9(ExchangeFunctions.java:141) ~[spring-webflux-5.3.24.jar:5.3.24] at reactor.core.publisher.MonoErrorSupplied.subscribe(MonoErrorSupplied.java:55) ~[reactor-core-3.4.25.jar:3.4.25] ...
问题原因及解决方法
1. WebClient URI 使用方式错误
问题:代码中使用URI("http://my-service/endpoint")创建URI对象,会绕过Spring Cloud LoadBalancer的服务名解析逻辑,直接将my-service当作主机名解析,导致DNS查询失败。
解决:改用字符串形式传入URI,让LoadBalanced WebClient能识别并替换服务名:
.uri("http://my-service/endpoint")
2. 自定义服务实例供应商类存在语法错误
问题:
- 类名拼写错误:
ServiceInstanceListSupplerImpl应为ServiceInstanceListSupplierImpl(Suppler → Supplier) - Lambda表达式语法错误:
mapIndexed { index, s -应为mapIndexed { index, s ->
这些错误会导致该类无法正常编译或实例化,LoadBalancer无法获取服务实例列表。
解决:修正类名和语法错误:
class LoadBalancerConfig { @Bean @Primary fun serviceInstanceListSupplier(): ServiceInstanceListSupplier { return ServiceInstanceListSupplierImpl("my-service") } } class ServiceInstanceListSupplierImpl(private val serviceId: String) : ServiceInstanceListSupplier { override fun getServiceId(): String { return serviceId } override fun get(): Flux<List<ServiceInstance>> { return Flux.just(listOf("localhost").mapIndexed { index, s -> DefaultServiceInstance(index.toString(), serviceId, s, 8088, true) }) } }
注意:DefaultServiceInstance的第三个参数是主机名(不是完整URL),所以传入localhost而非http://localhost
3. 简单发现客户端配置格式错误
问题:配置文件中my-service[0].uri的格式不符合Spring Boot YAML数组配置规范,导致SimpleDiscoveryClient无法正确加载服务实例。
解决:修正为正确的数组格式:
spring: cloud: discovery: client: simple: instances: my-service: - uri: http://localhost:8088
4. 自定义配置与默认发现客户端冲突
问题:LoadBalancerConfig中使用@Primary注解标记自定义ServiceInstanceListSupplier,但如果同时启用了SimpleDiscoveryClient,可能存在Bean加载优先级冲突,导致自定义供应商未被正确使用。
解决:
- 如果不需要自定义供应商,可删除
LoadBalancerConfig及相关类,仅依靠SimpleDiscoveryClient配置即可 - 如果需要自定义供应商,确保类无语法错误,且
@LoadBalancerClient注解正确关联到该配置类
内容的提问来源于stack exchange,提问作者Vlad
相关产品推荐
相关产品推荐

