Spring WebClient忽略baseUrl端口号问题排查求助
问题原因与解决方案
原因
问题出在你使用的LoadBalancedExchangeFilterFunction上。这个过滤器是为服务发现场景设计的:它会把WebClient的baseUrl当作服务名,而非具体的URL地址,然后去服务注册中心(比如Eureka、Nacos)查找对应的服务实例,再替换成实例的实际地址。
在你的测试场景中,你设置的baseUrl是http://localhost:9999,过滤器会把localhost识别成服务名,尝试去注册中心查找这个服务。但测试环境没有启动服务注册中心,过滤器找不到对应的服务实例,就会回退到默认逻辑,直接去掉端口,请求http://localhost/api/schedules,最终导致503错误。
解决方案
有两种简单的处理方式:
1. 测试时移除负载均衡过滤器
在测试类中重新定义ScheduleClient的Bean,不添加LoadBalancedExchangeFilterFunction:
@SpringBootTest public class ScheduleClientTest { @Bean ScheduleClient testScheduleClient(@Value("${schedule-service.base-url}") String baseUrl) { WebClient webClient = WebClient.builder() .baseUrl(baseUrl) // 不添加负载均衡过滤器 .build(); HttpServiceProxyFactory httpServiceProxyFactory = HttpServiceProxyFactory .builder(WebClientAdapter.forClient(webClient)) .build(); return httpServiceProxyFactory.createClient(ScheduleClient.class); } @DynamicPropertySource static void overrideScheduleServiceBaseUrl(DynamicPropertyRegistry registry) { registry.add( "schedule-service.base-url", () -> "http://localhost:9999"); } // 测试方法... }
2. 给配置类添加环境条件
修改原ScheduleConfig,区分测试与非测试环境的Bean定义:
@Configuration @RequiredArgsConstructor public class ScheduleConfig { private final LoadBalancedExchangeFilterFunction filterFunction; @Bean @Profile("!test") // 非测试环境加载带负载均衡的Bean ScheduleClient scheduleClient( @Value("${schedule-service.base-url}") String baseUrl ) { WebClient webClient = WebClient.builder() .baseUrl(baseUrl) .filter(filterFunction) .build(); HttpServiceProxyFactory httpServiceProxyFactory = HttpServiceProxyFactory .builder(WebClientAdapter.forClient(webClient)) .build(); return httpServiceProxyFactory.createClient(ScheduleClient.class); } @Bean @Profile("test") // 测试环境加载不带负载均衡的Bean ScheduleClient testScheduleClient( @Value("${schedule-service.base-url}") String baseUrl ) { WebClient webClient = WebClient.builder() .baseUrl(baseUrl) .build(); HttpServiceProxyFactory httpServiceProxyFactory = HttpServiceProxyFactory .builder(WebClientAdapter.forClient(webClient)) .build(); return httpServiceProxyFactory.createClient(ScheduleClient.class); } }
这样测试时会使用不带负载均衡过滤器的WebClient,baseUrl的端口会被正常保留,请求能正确发送到WireMock的9999端口。
内容的提问来源于stack exchange,提问作者karixdev
相关产品推荐
相关产品推荐

