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

配置Spring WebClient与Spring Cloud LoadBalancer:解决ROLE-SERVICE解析问题

问题分析与解决方案

核心问题原因

你遇到的UnknownHostException是因为直接给WebClient设置baseUrl时,@LoadBalanced注解无法拦截处理baseUrl中的服务名,导致JVM尝试通过DNS解析ROLE-SERVICE,而非通过Spring Cloud LoadBalancer从Eureka获取实例。

修复方案

方案1:重构WebClient配置,使用带负载均衡的构建器

不要直接在WebClient实例中设置baseUrl,而是给WebClient.Builder添加@LoadBalanced注解,基于这个构建器创建具体的WebClient实例:

@Configuration
@LoadBalancerClients({
    @LoadBalancerClient(name = "ROLE-SERVICE", configuration = LoadBalancerConfiguration.class),
    @LoadBalancerClient(name = "USER-SERVICE", configuration = LoadBalancerConfiguration.class)
})
public class WebClientConfig {    

    @Bean
    @LoadBalanced
    public WebClient.Builder webClientBuilder() {
        return WebClient.builder()
                .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
    }

    @Bean
    public WebClient webClientUserService(WebClient.Builder builder) {
        return builder.baseUrl("http://USER-SERVICE").build();
    }

    @Bean
    public WebClient webClientRoleService(WebClient.Builder builder) {
        return builder.baseUrl("http://ROLE-SERVICE").build();
    }
}

关键逻辑:

  • @LoadBalanced注解作用于WebClient.Builder,让负载均衡逻辑注入到构建器中
  • 基于带负载均衡能力的构建器创建实例,此时baseUrl中的服务名会被正确解析为Eureka中的实例地址

方案2:手动添加负载均衡过滤器

如果不想调整构建方式,可以给WebClient添加LoadBalancerExchangeFilterFunction来拦截请求:

@Configuration
@LoadBalancerClients({
    @LoadBalancerClient(name = "ROLE-SERVICE", configuration = LoadBalancerConfiguration.class),
    @LoadBalancerClient(name = "USER-SERVICE", configuration = LoadBalancerConfiguration.class)
})
public class WebClientConfig {    

    @Bean
    public WebClient webClientUserService(LoadBalancerExchangeFilterFunction filterFunction) {
        return WebClient
                .builder()
                .baseUrl("http://USER-SERVICE")
                .filter(filterFunction)
                .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
                .build();
    }

    @Bean
    public WebClient webClientRoleService(LoadBalancerExchangeFilterFunction filterFunction) {
        return WebClient
                .builder()
                .baseUrl("http://ROLE-SERVICE")
                .filter(filterFunction)
                .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
                .build();
    }
}

这个过滤器会自动将服务名替换为Eureka中注册的具体实例地址,实现负载均衡。

方案3:测试友好的配置方式(推荐)

将服务地址配置到配置文件中,方便测试时快速替换:

  1. 在application.yml中添加:
services:
  user-service: http://USER-SERVICE
  role-service: http://ROLE-SERVICE
  1. 修改WebClient配置类:
@Configuration
@LoadBalancerClients({
    @LoadBalancerClient(name = "ROLE-SERVICE", configuration = LoadBalancerConfiguration.class),
    @LoadBalancerClient(name = "USER-SERVICE", configuration = LoadBalancerConfiguration.class)
})
public class WebClientConfig {    

    @Value("${services.user-service}")
    private String userServiceBaseUrl;

    @Value("${services.role-service}")
    private String roleServiceBaseUrl;

    @Bean
    @LoadBalanced
    public WebClient.Builder webClientBuilder() {
        return WebClient.builder()
                .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
    }

    @Bean
    public WebClient webClientUserService(WebClient.Builder builder) {
        return builder.baseUrl(userServiceBaseUrl).build();
    }

    @Bean
    public WebClient webClientRoleService(WebClient.Builder builder) {
        return builder.baseUrl(roleServiceBaseUrl).build();
    }
}

测试时只需在application-test.yml中替换为测试地址即可,无需修改代码。

额外验证点

  • 确认项目已引入spring-cloud-starter-loadbalancer依赖(Spring Cloud 2020.0+版本默认移除了Ribbon,需手动引入)
  • 检查Eureka客户端配置的fetch-registry: true是否生效,确保服务实例列表已被拉取
  • 验证ROLE-SERVICE在Eureka控制台中的实例状态为UP

内容的提问来源于stack exchange,提问作者Vincent Schiller

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 01:31:01