Spring + Eureka Connection 拒绝注册服务

Spring + Eureka Connection refused to registered service

问题是抛出了 ConnectException。进入 Cairo 容器,ping 讨论容器成功,端点通过 cURL 按预期响应。送入 curl 的 URL 是 http://discussion/discussion/c3f3e424-bc67-4984-b808-e14ddf493766,因为这是 Docker Compose 生成的服务的名称。在外部,没有端口是 80 或 8080 - 每个端口都是大于 8080 的迭代。

我希望我的 Spring 实现功能完美。出于某种原因,当我 运行 三个 Spring 引导应用程序(discussion-service(端口 8080)、cairo-service(端口 8081)和 nile-service(端口 8761) - 本地尤里卡服务器)它工作得很好。

最后,值得注意的是,我才刚刚开始学习此设置几天。

2020-04-14 19:38:47.850 DEBUG 1 --- [nio-8080-exec-2] o.s.web.client.RestTemplate              : Accept=[application/json, application/*+json]
2020-04-14 19:38:48.088  INFO 1 --- [nio-8080-exec-2] c.netflix.config.ChainedDynamicProperty  : Flipping property: discussion-service.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.ac
tiveConnectionsLimit = 2147483647                                                                                                                                                                                                        2020-04-14 19:38:48.142  INFO 1 --- [nio-8080-exec-2] c.n.u.concurrent.ShutdownEnabledTimer    : Shutdown hook installed for: NFLoadBalancer-PingTimer-discussion-service
2020-04-14 19:38:48.143  INFO 1 --- [nio-8080-exec-2] c.netflix.loadbalancer.BaseLoadBalancer  : Client: discussion-service instantiated a LoadBalancer: DynamicServerListLoadBalancer:{NFLoadBalancer:name=discussion-service,current li
st of Servers=[],Load balancer stats=Zone stats: {},Server stats: []}ServerList:null
2020-04-14 19:38:48.154  INFO 1 --- [nio-8080-exec-2] c.n.l.DynamicServerListLoadBalancer      : Using serverListUpdater PollingServerListUpdater                                                                                        2020-04-14 19:38:48.195  INFO 1 --- [nio-8080-exec-2] c.netflix.config.ChainedDynamicProperty  : Flipping property: discussion-service.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.ac
tiveConnectionsLimit = 2147483647
2020-04-14 19:38:48.198  INFO 1 --- [nio-8080-exec-2] c.n.l.DynamicServerListLoadBalancer      : DynamicServerListLoadBalancer for client discussion-service initialized: DynamicServerListLoadBalancer:{NFLoadBalancer:name=discussion-s
ervice,current list of Servers=[nile:8080],Load balancer stats=Zone stats: {defaultzone=[Zone:defaultzone;      Instance count:1;       Active connections count: 0;    Circuit breaker tripped count: 0;       Active connections per se
rver: 0.0;]
},Server stats: [[Server:nile:8080;     Zone:defaultZone;       Total Requests:0;       Successive connection failure:0;        Total blackout seconds:0;       Last connection made:Thu Jan 01 00:00:00 GMT 1970;      First connection
made: Thu Jan 01 00:00:00 GMT 1970;     Active Connections:0;   total failure count in last (1000) msecs:0;     average resp time:0.0;  90 percentile resp time:0.0;    95 percentile resp time:0.0;    min resp time:0.0;      max resp
time:0.0;       stddev resp time:0.0]
]}ServerList:org.springframework.cloud.netflix.ribbon.eureka.DomainExtractingServerList@283933a4
2020-04-14 19:38:48.234 DEBUG 1 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet        : Failed to complete request: org.springframework.web.client.ResourceAccessException: I/O error on GET request for "http://discussion-serv
ice/discussion/c3f3e424-bc67-4984-b808-e14ddf493766": Connection refused; nested exception is java.net.ConnectException: Connection refused
2020-04-14 19:38:48.242 ERROR 1 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception i
s org.springframework.web.client.ResourceAccessException: I/O error on GET request for "http://discussion-service/discussion/c3f3e424-bc67-4984-b808-e14ddf493766": Connection refused; nested exception is java.net.ConnectException: Co
nnection refused] with root cause

java.net.ConnectException: Connection refused
        at java.base/sun.nio.ch.Net.connect0(Native Method) ~[na:na]
        at java.base/sun.nio.ch.Net.connect(Net.java:503) ~[na:na]
        at java.base/sun.nio.ch.Net.connect(Net.java:492) ~[na:na]
        at java.base/sun.nio.ch.NioSocketImpl.connect(NioSocketImpl.java:588) ~[na:na]
        at java.base/java.net.Socket.connect(Socket.java:648) ~[na:na]
        at java.base/java.net.Socket.connect(Socket.java:597) ~[na:na]
        at java.base/sun.net.NetworkClient.doConnect(NetworkClient.java:182) ~[na:na]
        at java.base/sun.net.www.http.HttpClient.openServer(HttpClient.java:474) ~[na:na]
        at java.base/sun.net.www.http.HttpClient.openServer(HttpClient.java:569) ~[na:na]
        at java.base/sun.net.www.http.HttpClient.<init>(HttpClient.java:242) ~[na:na]
        at java.base/sun.net.www.http.HttpClient.New(HttpClient.java:341) ~[na:na]
        at java.base/sun.net.www.http.HttpClient.New(HttpClient.java:362) ~[na:na]
        at java.base/sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:1256) ~[na:na]
        at java.base/sun.net.www.protocol.http.HttpURLConnection.plainConnect0(HttpURLConnection.java:1194) ~[na:na]
        at java.base/sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:1082) ~[na:na]
        at java.base/sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:1016) ~[na:na]
        at org.springframework.http.client.SimpleBufferingClientHttpRequest.executeInternal(SimpleBufferingClientHttpRequest.java:76) ~[spring-web-5.2.5.RELEASE.jar!/:5.2.5.RELEASE]
        at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:48) ~[spring-web-5.2.5.RELEASE.jar!/:5.2.5.RELEASE]
        at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:53) ~[spring-web-5.2.5.RELEASE.jar!/:5.2.5.RELEASE]
        at org.springframework.http.client.InterceptingClientHttpRequest$InterceptingRequestExecution.execute(InterceptingClientHttpRequest.java:109) ~[spring-web-5.2.5.RELEASE.jar!/:5.2.5.RELEASE]
        at org.springframework.cloud.client.loadbalancer.LoadBalancerRequestFactory.lambda$createRequest[=11=](LoadBalancerRequestFactory.java:61) ~[spring-cloud-commons-2.2.2.RELEASE.jar!/:2.2.2.RELEASE]
        at org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient.execute(RibbonLoadBalancerClient.java:144) ~[spring-cloud-netflix-ribbon-2.2.2.RELEASE.jar!/:2.2.2.RELEASE]
        at org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient.execute(RibbonLoadBalancerClient.java:125) ~[spring-cloud-netflix-ribbon-2.2.2.RELEASE.jar!/:2.2.2.RELEASE]
        at org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient.execute(RibbonLoadBalancerClient.java:99) ~[spring-cloud-netflix-ribbon-2.2.2.RELEASE.jar!/:2.2.2.RELEASE]
        at org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor.intercept(LoadBalancerInterceptor.java:58) ~[spring-cloud-commons-2.2.2.RELEASE.jar!/:2.2.2.RELEASE]
        at org.springframework.http.client.InterceptingClientHttpRequest$InterceptingRequestExecution.execute(InterceptingClientHttpRequest.java:93) ~[spring-web-5.2.5.RELEASE.jar!/:5.2.5.RELEASE]
        at org.springframework.http.client.InterceptingClientHttpRequest.executeInternal(InterceptingClientHttpRequest.java:77) ~[spring-web-5.2.5.RELEASE.jar!/:5.2.5.RELEASE]
        at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:48) ~[spring-web-5.2.5.RELEASE.jar!/:5.2.5.RELEASE]
        at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:53) ~[spring-web-5.2.5.RELEASE.jar!/:5.2.5.RELEASE]
        at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:739) ~[spring-web-5.2.5.RELEASE.jar!/:5.2.5.RELEASE]
        at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:674) ~[spring-web-5.2.5.RELEASE.jar!/:5.2.5.RELEASE]
        at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:315) ~[spring-web-5.2.5.RELEASE.jar!/:5.2.5.RELEASE]
        at com.supaham.learn.controller.QuestionController.discussion(QuestionController.kt:53) ~[classes!/:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
        at java.base/java.lang.reflect.Method.invoke(Method.java:564) ~[na:na]
        at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190) ~[spring-web-5.2.5.RELEASE.jar!/:5.2.5.RELEASE]
        at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) ~[spring-web-5.2.5.RELEASE.jar!/:5.2.5.RELEASE]
        at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105) ~[spring-webmvc-5.2.5.RELEASE.jar!/:5.2.5.RELEASE]
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:879) ~[spring-webmvc-5.2.5.RELEASE.jar!/:5.2.5.RELEASE]
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:793) ~[spring-webmvc-5.2.5.RELEASE.jar!/:5.2.5.RELEASE]
        at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.2.5.RELEASE.jar!/:5.2.5.RELEASE]
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040) ~[spring-webmvc-5.2.5.RELEASE.jar!/:5.2.5.RELEASE]
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943) ~[spring-webmvc-5.2.5.RELEASE.jar!/:5.2.5.RELEASE]
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.2.5.RELEASE.jar!/:5.2.5.RELEASE]
        at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.2.5.RELEASE.jar!/:5.2.5.RELEASE]
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:634) ~[tomcat-embed-core-9.0.33.jar!/:9.0.33]
        at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.2.5.RELEASE.jar!/:5.2.5.RELEASE]
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:741) ~[tomcat-embed-core-9.0.33.jar!/:9.0.33]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.33.jar!/:9.0.33]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.33.jar!/:9.0.33]
        at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.33.jar!/:9.0.33]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.33.jar!/:9.0.33]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.33.jar!/:9.0.33]
        at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.2.5.RELEASE.jar!/:5.2.5.RELEASE]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.5.RELEASE.jar!/:5.2.5.RELEASE]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.33.jar!/:9.0.33]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.33.jar!/:9.0.33]
        at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.2.5.RELEASE.jar!/:5.2.5.RELEASE]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.5.RELEASE.jar!/:5.2.5.RELEASE]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.33.jar!/:9.0.33]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.33.jar!/:9.0.33]
        at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:109) ~[spring-boot-actuator-2.2.6.RELEASE.jar!/:2.2.6.RELEASE]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.5.RELEASE.jar!/:5.2.5.RELEASE]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.33.jar!/:9.0.33]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.33.jar!/:9.0.33]
        at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.2.5.RELEASE.jar!/:5.2.5.RELEASE]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.5.RELEASE.jar!/:5.2.5.RELEASE]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.33.jar!/:9.0.33]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.33.jar!/:9.0.33]
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.33.jar!/:9.0.33]
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) ~[tomcat-embed-core-9.0.33.jar!/:9.0.33]
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541) ~[tomcat-embed-core-9.0.33.jar!/:9.0.33]
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) ~[tomcat-embed-core-9.0.33.jar!/:9.0.33]
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.33.jar!/:9.0.33]
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) ~[tomcat-embed-core-9.0.33.jar!/:9.0.33]
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) ~[tomcat-embed-core-9.0.33.jar!/:9.0.33]
        at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:373) ~[tomcat-embed-core-9.0.33.jar!/:9.0.33]
        at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.33.jar!/:9.0.33]
        at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) ~[tomcat-embed-core-9.0.33.jar!/:9.0.33]
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1594) ~[tomcat-embed-core-9.0.33.jar!/:9.0.33]
        at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.33.jar!/:9.0.33]
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130) ~[na:na]
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630) ~[na:na]
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.33.jar!/:9.0.33]
        at java.base/java.lang.Thread.run(Thread.java:832) ~[na:na]

2020-04-14 19:38:48.249 DEBUG 1 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet        : "ERROR" dispatch for GET "/error", parameters={}
2020-04-14 19:38:48.254 DEBUG 1 --- [nio-8080-exec-2] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController#errorHtml(HttpServletRequest, HttpServletRespons
e)
2020-04-14 19:38:48.276 DEBUG 1 --- [nio-8080-exec-2] o.s.w.s.v.ContentNegotiatingViewResolver : Selected 'text/html' given [text/html, text/html;q=0.8]
2020-04-14 19:38:48.282 DEBUG 1 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet        : Exiting from "ERROR" dispatch, status 500
2020-04-14 19:38:49.158  INFO 1 --- [erListUpdater-0] c.netflix.config.ChainedDynamicProperty  : Flipping property: discussion-service.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.ac
tiveConnectionsLimit = 2147483647

经过一些胡闹和大量的水后,结果是服务器隐式在容器的端口8080上注册。

考虑到容器能够通过 cURL 进行通信,我对可能导致此问题的原因感到困惑。我 @Autowired EurekaDiscoveryClient 并开始挖掘其属性,特别是搜索与服务有关的任何内容。

  1. client.services: returns [cairo-service, discussion-service]。太棒了!
  2. discussion-service 的第一个实例的 ID 为 fc8feb8bb803:discussion-service,与 Eureka UI 所说的完全一样!
  3. 查看同一实例中的 metadata:returns {management.port=8080} 的地图。嗯,听起来很相关。

在这一切中间的某个地方,我的脑海里浮现出最轻微的可能性,即上述 "id" 也应该代表它的端口,类似于。你瞧,端口以某种方式参与其中。

在我的本地开发机器上,Eureka UI 声明 discussion-service 已注册到 MY-PC:discussion-service。这里要说明的重要一点是 cairo-service 注册到 MY-PC:cairo-service:8081,使用明确定义的端口 8081。请注意,我目前没有使用 docker 进行开发,而只是 运行 根据需要提供服务(在和平端口上),因此为什么使用 MY-PC 而不是 docker 容器主机名。系统功能如前所述,cairo-service可以达到discussion-service。为什么?好吧,事实证明,当 Eureka 在其自己的网络(或主机?)上时,在到达正确的地址和端口方面做得更好。

当服务被隔离时,Eureka 无法表示与 discussion-service 的正确连接,因为它未能将默认隐含端口 8080 作为 URL 的一部分包含在内,导致消费者使用默认 HTTP 端口 80 引用 URL,例如http://discussion-service:80/discussion/c3f3e424-bc67-4984-b808-e14ddf493766.

我们如何解决这个问题?

事实证明,明确设置服务器端口会导致 Eureka 将其作为服务 ID 的一部分进行拾取。这个问题可以通过多种方式解决,但我的偏好是最不受限制的。我在 application.properties 文件中使用 server.port 属性。在我的例子中,我使用 application.yml

server:
  port: 8080

就这样,一整天的头痛在几个字内就解决了。

我要感谢 Spring 团队让这个工具如此易于使用。然而,这也是罪魁祸首,因为框架内使用了太多工具,还有我的环境,这使得很难理解到底是哪一点失败了