Spring Cloud微服务调用报错:无法解析inventory-service主机
微服务通信UnknownHostException问题排查
问题场景
使用Java 17、Spring Boot v3.1.3及Spring Cloud栈实现微服务间通信,向http://localhost:8081/api/order发送POST请求时,order-service抛出UnknownHostException,无法解析inventory-service服务名。
报错信息
java.net.UnknownHostException: Failed to resolve 'inventory-service' [A(1), AAAA(28)] after 6 queries at io.netty.resolver.dns.DnsResolveContext.finishResolve(DnsResolveContext.java:1097) ~[netty-resolver-dns-4.1.97.Final.jar:4.1.97.Final] at io.netty.resolver.dns.DnsResolveContext.tryToFinishResolve(DnsResolveContext.java:1044) ~[netty-resolver-dns-4.1.97.Final.jar:4.1.97.Final] at io.netty.resolver.dns.DnsResolveContext.query(DnsResolveContext.java:432) ~[netty-resolver-dns-4.1.97.Final.jar:4.1.97.Final] at io.netty.resolver.dns.DnsResolveContext.onResponse(DnsResolveContext.java:662) ~[netty-resolver-dns-4.1.97.Final.jar:4.1.97.Final] at io.netty.resolver.dns.DnsResolveContext.access$500(DnsResolveContext.java:66) ~[netty-resolver-dns-4.1.97.Final.jar:4.1.97.Final] at io.netty.resolver.dns.DnsResolveContext$2.operationComplete(DnsResolveContext.java:489) ~[netty-resolver-dns-4.1.97.Final.jar:4.1.97.Final] at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:590) ~[netty-common-4.1.97.Final.jar:4.1.97.Final] at io.netty.util.concurrent.DefaultPromise.notifyListeners0(DefaultPromise.java:583) ~[netty-common-4.1.97.Final.jar:4.1.97.Final] at io.netty.util.concurrent.DefaultPromise.notifyListenersNow(DefaultPromise.java:559) ~[netty-common-4.1.97.Final.jar:4.1.97.Final] at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:492) ~[netty-common-4.1.97.Final.jar:4.1.97.Final] at io.netty.util.concurrent.DefaultPromise.setValue0(DefaultPromise.java:636) ~[netty-common-4.1.97.Final.jar:4.1.97.Final] at io.netty.util.concurrent.DefaultPromise.setSuccess0(DefaultPromise.java:625) ~[netty-common-4.1.97.Final.jar:4.1.97.Final] at io.netty.util.concurrent.DefaultPromise.trySuccess(DefaultPromise.java:105) ~[netty-common-4.1.97.Final.jar:4.1.97.Final] at io.netty.resolver.dns.DnsQueryContext.trySuccess(DnsQueryContext.java:317) ~[netty-resolver-dns-4.1.97.Final.jar:4.1.97.Final] at io.netty.resolver.dns.DnsQueryContext.finishSuccess(DnsQueryContext.java:309) ~[netty-resolver-dns-4.1.97.Final.jar:4.1.97.Final] at io.netty.resolver.dns.DnsNameResolver$DnsResponseHandler.channelRead(DnsNameResolver.java:1392) ~[netty-resolver-dns-4.1.97.Final.jar:4.1.97.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444) ~[netty-transport-4.1.97.Final.jar:4.1.97.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) ~[netty-transport-4.1.97.Final.jar:4.1.97.Final] at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) ~[netty-transport-4.1.97.Final.jar:4.1.97.Final] at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103) ~[netty-codec-4.1.97.Final.jar:4.1.97.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444) ~[netty-transport-4.1.97.Final.jar:4.1.97.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) ~[netty-transport-4.1.97.Final.jar:4.1.97.Final] at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) ~[netty-transport-4.1.97.Final.jar:4.1.97.Final] at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) ~[netty-transport-4.1.97.Final.jar:4.1.97.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:440) ~[netty-transport-4.1.97.Final.jar:4.1.97.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) ~[netty-transport-4.1.97.Final.jar:4.1.97.Final] at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) ~[netty-transport-4.1.97.Final.jar:4.1.97.Final] at io.netty.channel.nio.AbstractNioMessageChannel$NioMessageUnsafe.read(AbstractNioMessageChannel.java:97) ~[netty-transport-4.1.97.Final.jar:4.1.97.Final] at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:788) ~[netty-transport-4.1.97.Final.jar:4.1.97.Final] at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:724) ~[netty-transport-4.1.97.Final.jar:4.1.97.Final] at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:650) ~[netty-transport-4.1.97.Final.jar:4.1.97.Final] at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562) ~[netty-transport-4.1.97.Final.jar:4.1.97.Final] at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997) ~[netty-common-4.1.97.Final.jar:4.1.97.Final] at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.97.Final.jar:4.1.97.Final] at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.97.Final.jar:4.1.97.Final] at java.base/java.lang.Thread.run(Thread.java:1589) ~[na:na]
相关配置
依赖配置(pom.xml)
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> <version>4.0.2</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-loadbalancer</artifactId> <version>3.1.6</version> </dependency>
WebClient配置类
@Configuration public class WebClientConfig { @Bean @LoadBalanced public WebClient.Builder webClientBuilder() { return WebClient.builder(); } }
OrderService核心代码
private final WebClient.Builder webClientBuilder; public void placeOrder(OrderRequest orderRequest) { Order order = new Order(); order.setOrderNumber(UUID.randomUUID().toString()); List<OrderLineItems> orderLineItems = orderRequest.getOrderLineItemsDto() .stream() .map(this::mapToDto) .toList(); order.setOrderLineItems(orderLineItems); List<String> skuCodes = order.getOrderLineItems().stream() .map(OrderLineItems::getSkuCode) .toList(); InventoryResponse[] inventoryResponses = webClientBuilder.build().get() .uri("http://inventory-service/api/inventory", uriBuilder -> uriBuilder.queryParam("skuCode", skuCodes).build()) .retrieve() .bodyToMono(InventoryResponse[].class) .block(); }
各服务配置文件
order-service application.properties
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/order-service spring.datasource.username=username spring.datasource.password=password spring.jpa.hibernate.ddl-auto=update spring.application.name=order-service server.port=8081 eureka.client.service-url.default-zone=http://localhost:8761/eureka eureka.instance.prefer-ip-address=true eureka.instance.hostname=localhost
inventory-service application.properties
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3307/inventory-service spring.datasource.username=root spring.datasource.password=1234 spring.jpa.hibernate.ddl-auto=create-drop spring.application.name=inventory-service server.port=0 eureka.client.service-url.default-zone=http://localhost:8761/eureka
discovery-server application.properties
server.port=8761 eureka.instance.hostname=localhost eureka.client.register-with-eureka=false eureka.client.fetch-registry=false eureka.client.service-url.defaultZone=http://localhost:${server.port}/eureka/ eureka.instance.prefer-ip-address=true
排查与解决方法
确认服务注册状态
- 访问Eureka控制台
http://localhost:8761,检查inventory-service是否已成功注册。若未注册:- 查看inventory-service启动日志,排查注册失败的报错信息
- 确认inventory-service的
eureka.client.service-url.default-zone与discovery-server地址完全一致
- 访问Eureka控制台
修复order-service的Eureka配置冲突
- order-service中
eureka.instance.hostname=localhost和prefer-ip-address=true配置冲突,prefer-ip-address=true会优先使用IP注册,建议移除eureka.instance.hostname=localhost
- order-service中
强制LoadBalancer使用Eureka解析
- 在order-service的application.properties中添加配置:
spring.cloud.loadbalancer.eureka.enabled=true - 确保WebClient使用的是带有
@LoadBalanced注解的Builder实例
- 在order-service的application.properties中添加配置:
禁用DNS缓存
- 添加JVM启动参数
-Dsun.net.inetaddr.ttl=0,避免JVM DNS缓存导致服务名无法实时解析
- 添加JVM启动参数
等待服务注册完成
- 服务启动后需等待1-2分钟完成注册与心跳同步,不要在服务刚启动时立即调用接口
内容的提问来源于stack exchange,提问作者Corvo
相关产品推荐
相关产品推荐

