You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 23:00:27