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

Spring Boot/Cloud调用inventory-service报UnknownHostException

问题根因

该异常是Spring Boot 2.7.0 搭配 Spring Cloud 2021.0.x 版本栈下,WebClient + Netty + Eureka + Spring Cloud LoadBalancer 组合的典型适配问题,触发逻辑完全匹配描述场景:

  • 服务调用方使用默认基于Netty实现的WebClient发起调用
  • 被调用方配置server.port=0随机端口+随机实例ID启动
  • 单实例启动时,Spring Cloud LoadBalancer的服务实例列表默认懒加载,首次请求触发时缓存未完成实例列表拉取,请求链路直接绕过负载均衡逻辑,将服务名作为普通域名交给Netty原生DNS模块发起公网解析,最终抛出java.net.UnknownHostException: Failed to resolve 'inventory-service' after 4 queries
  • 多实例启动时,Eureka注册表的多次变更事件会提前触发LoadBalancer缓存刷新,首次请求时服务实例列表已完成加载,因此调用可正常执行。
修复方案

按以下顺序配置即可解决问题:

1. 修正WebClient的Bean配置

必须通过带@LoadBalanced注解的WebClient.Builder构造实例,直接调用WebClient.create()静态方法不会注入负载均衡的服务名解析过滤器:

@Configuration
public class WebClientConfig {
    // 注入带负载均衡能力的WebClient构造器
    @Bean
    @LoadBalanced
    public WebClient.Builder loadBalancedWebClientBuilder() {
        // 强制使用JDK内置地址解析器,彻底绕过Netty原生DNS逻辑
        HttpClient httpClient = HttpClient.create()
                .resolver(DefaultAddressResolverGroup.INSTANCE);
        return WebClient.builder()
                .clientConnector(new ReactorClientHttpConnector(httpClient));
    }
}

业务类注入时使用构造器生成WebClient实例:

@Service
public class OrderBizService {
    private final WebClient webClient;

    // 注入配置好的Builder构造实例
    public OrderBizService(WebClient.Builder loadBalancedWebClientBuilder) {
        this.webClient = loadBalancedWebClientBuilder.build();
    }

    // 调用示例
    public InventoryInfo queryInventory(String skuId) {
        return webClient.get()
                .uri("http://inventory-service/api/inventory?skuId=" + skuId)
                .retrieve()
                .bodyToMono(InventoryInfo.class)
                .block();
    }
}

2. 添加调用方配置(order-service的application.yml)

关闭Netty原生DNS,调整LoadBalancer缓存加载策略,避免懒加载导致的解析绕过问题:

spring:
  cloud:
    loadbalancer:
      cache:
        enabled: true
        ttl: 5s
        capacity: 128
      health-check:
        initial-delay: 1s
        interval: 5s
  webclient:
    reactor:
      client:
        dns:
          resolver:
            native: false

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
    fetch-registry: true
    register-with-eureka: true
    # 启动后立即拉取注册表,关闭延迟拉取
    initial-instance-info-replication-interval-seconds: 1

3. 调整被调用方配置(inventory-service的application.yml)

修正随机实例ID规则,缩短心跳同步间隔,让单实例启动后快速同步到Eureka注册表:

server:
  port: 0

spring:
  application:
    name: inventory-service

eureka:
  instance:
    # 固定实例ID生成规则,避免单实例场景下元数据哈希不稳定
    instance-id: ${spring.application.name}:${random.value}
    # 优先使用IP注册,避免主机名解析冲突
    prefer-ip-address: true
    # 缩短心跳间隔,加速注册表同步
    lease-renewal-interval-in-seconds: 5
    lease-expiration-duration-in-seconds: 15
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
    fetch-registry: true
    register-with-eureka: true
验证流程
  1. 启动Eureka服务端,等待启动完成
  2. 启动单实例inventory-service,访问Eureka控制台确认服务状态为UP
  3. 启动order-service发起接口调用,DNS解析异常消失
  4. 启动多个inventory-service实例,验证负载均衡逻辑正常生效

注意:所有微服务间调用不要硬编码IP+端口,统一使用服务名发起请求,由负载均衡组件完成实例选择。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 11:42:17