通过网关进行 Api 调用会抛出 java.net.UnknownHostException,即使我能够使用给定的主机名直接访问应用程序
Spring Boot 版本:2.4.2
Spring-cloud.版本:2020.0.1
Java版本:11
注意: 同样适用于 Spring Boot 2.3.8.RELEASE 和云版本:Hoxton.SR9 与 Java 8
日志:
2021-02-10 14:25:05.398 ERROR 12632 --- [ctor-http-nio-4] a.w.r.e.AbstractErrorWebExceptionHandler : [efcc81fd-3] 500 Server Error for HTTP GET "/sample-order-service/sample-order"
java.net.UnknownHostException: failed to resolve 'MY-COMPUTER-NAME' after 2 queries
at io.netty.resolver.dns.DnsResolveContext.finishResolve(DnsResolveContext.java:1013) ~[netty-resolver-dns-4.1.58.Final.jar:4.1.58.Final]
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
|_ checkpoint ⇢ org.springframework.cloud.gateway.filter.WeightCalculatorWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ HTTP GET "/sample-order-service/sample-order" [ExceptionHandlingWebHandler]
Stack trace:
at io.netty.resolver.dns.DnsResolveContext.finishResolve(DnsResolveContext.java:1013) ~[netty-resolver-dns-4.1.58.Final.jar:4.1.58.Final]
at io.netty.resolver.dns.DnsResolveContext.tryToFinishResolve(DnsResolveContext.java:966) ~[netty-resolver-dns-4.1.58.Final.jar:4.1.58.Final]
at io.netty.resolver.dns.DnsResolveContext.query(DnsResolveContext.java:414) ~[netty-resolver-dns-4.1.58.Final.jar:4.1.58.Final]
at io.netty.resolver.dns.DnsResolveContext.onResponse(DnsResolveContext.java:625) ~[netty-resolver-dns-4.1.58.Final.jar:4.1.58.Final]
at io.netty.resolver.dns.DnsResolveContext.access$400(DnsResolveContext.java:63) ~[netty-resolver-dns-4.1.58.Final.jar:4.1.58.Final]
at io.netty.resolver.dns.DnsResolveContext$2.operationComplete(DnsResolveContext.java:458) ~[netty-resolver-dns-4.1.58.Final.jar:4.1.58.Final]
at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:578) ~[netty-common-4.1.58.Final.jar:4.1.58.Final]
at io.netty.util.concurrent.DefaultPromise.notifyListeners0(DefaultPromise.java:571) ~[netty-common-4.1.58.Final.jar:4.1.58.Final]
at io.netty.util.concurrent.DefaultPromise.notifyListenersNow(DefaultPromise.java:550) ~[netty-common-4.1.58.Final.jar:4.1.58.Final]
at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:491) ~[netty-common-4.1.58.Final.jar:4.1.58.Final]
at io.netty.util.concurrent.DefaultPromise.setValue0(DefaultPromise.java:616) ~[netty-common-4.1.58.Final.jar:4.1.58.Final]
at io.netty.util.concurrent.DefaultPromise.setSuccess0(DefaultPromise.java:605) ~[netty-common-4.1.58.Final.jar:4.1.58.Final]
at io.netty.util.concurrent.DefaultPromise.trySuccess(DefaultPromise.java:104) ~[netty-common-4.1.58.Final.jar:4.1.58.Final]
at io.netty.resolver.dns.DnsQueryContext.trySuccess(DnsQueryContext.java:201) ~[netty-resolver-dns-4.1.58.Final.jar:4.1.58.Final]
at io.netty.resolver.dns.DnsQueryContext.finish(DnsQueryContext.java:193) ~[netty-resolver-dns-4.1.58.Final.jar:4.1.58.Final]
at io.netty.resolver.dns.DnsNameResolver$DnsResponseHandler.channelRead(DnsNameResolver.java:1230) ~[netty-resolver-dns-4.1.58.Final.jar:4.1.58.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.58.Final.jar:4.1.58.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.58.Final.jar:4.1.58.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) ~[netty-transport-4.1.58.Final.jar:4.1.58.Final]
at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103) ~[netty-codec-4.1.58.Final.jar:4.1.58.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.58.Final.jar:4.1.58.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.58.Final.jar:4.1.58.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) ~[netty-transport-4.1.58.Final.jar:4.1.58.Final]
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) ~[netty-transport-4.1.58.Final.jar:4.1.58.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.58.Final.jar:4.1.58.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.58.Final.jar:4.1.58.Final]
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) ~[netty-transport-4.1.58.Final.jar:4.1.58.Final]
at io.netty.channel.nio.AbstractNioMessageChannel$NioMessageUnsafe.read(AbstractNioMessageChannel.java:93) ~[netty-transport-4.1.58.Final.jar:4.1.58.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:719) ~[netty-transport-4.1.58.Final.jar:4.1.58.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:655) ~[netty-transport-4.1.58.Final.jar:4.1.58.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:581) ~[netty-transport-4.1.58.Final.jar:4.1.58.Final]
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493) ~[netty-transport-4.1.58.Final.jar:4.1.58.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989) ~[netty-common-4.1.58.Final.jar:4.1.58.Final]
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.58.Final.jar:4.1.58.Final]
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.58.Final.jar:4.1.58.Final]
at java.base/java.lang.Thread.run(Thread.java:834) ~[na:an]
这让我很困扰,似乎是 Netty 和 Spring Boot 2.4.x 的问题。
但我设法通过使用
reactor.netty.http.client.HttpClient
和 DefaultAddressResolverGroup.INSTANCE
解析器解决了这个问题。
因此,当您创建 WebClient bean 时,您可以执行以下操作
@Bean
@Primary
public WebClient webClient() {
HttpClient httpClient = HttpClient.create().resolver(DefaultAddressResolverGroup.INSTANCE);
return WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(httpClient))
.build();
}
来自 Netty 文档的解释:
默认情况下,HttpClient 使用 Netty 的域名查找机制来异步解析域名。这是 JVM 内置阻塞解析器的替代方案。
有时,您可能想切换到 JVM 内置解析器。
将此配置添加到您的微服务中
eureka.instance.hostname=localhost
您可以在从 api-gateway 调用的所有微服务的 application.properties 文件中使用“ eureka.instance.prefer-ip-address=true ”。根本原因是您的 api 网关正在使用系统的用户名调用微服务,您需要使用系统的 IP 地址来调用。
将此属性添加到您的属性文件中:
eureka.instance.hostname=localhost
我也遇到了同样的问题,我可以通过更改spring的版本来解决它。这是我的 POM。
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.9.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.demo.microservices</groupId>
<artifactId>api-gateway</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>api-gateway</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
<spring-cloud.version>Hoxton.SR10</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
在 API 网关中添加以下属性应该可以解决此问题。在 Windows 平台上,API 网关的发现似乎不是默认的。
spring.cloud.discovery.enabled=true
请参阅以下链接。 “https://stackoverflow.com/questions/65333590/spring-cloud-api-gateway-routing-not-working
我遇到了同样的问题,发现这是因为 Spring 和 spring.cloud 版本。
我已经更改了我的 pom.xml,如下所示。在父级中,我评论了 2.4.4 并使用了 2.2.6,然后在属性中,我将 spring.cloud.version 2020.0.2 替换为 Hoxton.SR3 就是这样,然后它就开始工作了。
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<!-- <version>2.4.4</version> -->
<version>2.2.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<java.version>11</java.version>
<!-- <spring-cloud.version>2020.0.2</spring-cloud.version> -->
<spring-cloud.version>Hoxton.SR3</spring-cloud.version>
</properties>
我已经通过另一种方式解决了这个问题。 对于那些使用 Spring Webflux + Spring Cloud 遇到此问题的人,请执行以下操作:
DiscoveryClient discoveryClient;
private String getGatewayBaseUrl(ServiceInstance instance) {
return instance.getUri().toString();
}
getGatewayBaseUrl(discoveryClient.getInstances("YOUR_GATEWAY_SERVICE_NAME").get(0)
也许这不是解决问题的最好方法,或者可能不是最正确的方法,但是工作
这确实让我感到不安,但我找到了适合我的解决方案。我使用的是 Spring Boot 3、Java 17 和 CentOS 8。 我必须编辑文件
/etc/hostname.
最初,它以 cantos
作为主机。删除了该文件中的所有内容,它对我有用。希望这有帮助