Spring Cloud 应用程序 - 在 Tomcat 上部署后 zuul 超时
Posted
技术标签:
【中文标题】Spring Cloud 应用程序 - 在 Tomcat 上部署后 zuul 超时【英文标题】:Spring Cloud app - zuul timeout after deploying on Tomcat 【发布时间】:2016-06-24 06:46:32 【问题描述】:我正在尝试使用 Spring Cloud 设置几个服务,在我将 Eureka 客户端服务部署到 Tomcat 之前,一切似乎都运行良好。当我通过网关应用调用服务时,出现以下错误:
o.s.c.n.z.filters.post.SendErrorFilter : Error during filtering
com.netflix.zuul.exception.ZuulException: Forwarding error
...
Caused by: com.netflix.hystrix.exception.HystrixRuntimeException: hello timed-out and no fallback available.
...
Caused by: java.util.concurrent.TimeoutException: null
然而,它在 Eclipse 中完美运行。当我从 Tomcat 运行发现和网关服务并从 eclipse 运行 Eureka 客户端服务时,它甚至可以工作。但是一旦我在 tomcat 上运行相同的服务,我就会得到错误。
我正在使用 Brixton.M5、Java 8 和 Tomcat 8。
再次,代码似乎可以工作,问题是它在部署到 Tomcat 后无法工作。
我有一个用于发现和网关服务的 Tomcat 实例,还有一个用于 Eureka 客户端服务的 Tomcat 实例。
这是一些代码和配置..
DiscoveryServerApp
@SpringBootApplication
@EnableEurekaServer
public class DiscoveryServerApp extends SpringBootServletInitializer
public static void main(String[] args)
SpringApplication.run(DiscoveryServerApp.class, args);
DiscoveryServer - application.yml
# Configure this Discovery Server
eureka:
instance:
hostname: discovery
client: # Not a client, don't register with yourself
registerWithEureka: false
fetchRegistry: false
serviceUrl:
defaultZone: http://localhost:1111/discovery/eureka/
server:
port: 1111 # HTTP (Tomcat) port
context-path: /discovery
DiscoveryServer - bootstrap.yml
spring:
application:
name: discovery
jmx:
default-domain: com.example.cloud.discovery
网关应用程序
@SpringCloudApplication
@EnableZuulProxy
public class GatewayApplication extends SpringBootServletInitializer
public static void main(String[] args)
SpringApplication.run(GatewayApplication.class, args);
GatewayApplication - application.yml
# Discovery Server Access
eureka:
client:
serviceUrl:
defaultZone: http://localhost:1111/discovery/eureka/
instance:
instanceId: $spring.application.name:$spring.application.instance_id:$random.value
# HTTP Server
server:
port: 4444 # HTTP (Tomcat) port
context-path: /api
GatewayApplication - bootstrap.yml
# Spring properties
spring:
application:
name: gateway-service # Identify this application
jmx:
default-domain: com.example.cloud.gateway
encrypt:
failOnError: false
虚拟应用程序
@SpringCloudApplication
@RestController
public class DummyApplication extends SpringBootServletInitializer
public static void main(String[] args)
SpringApplication.run(DummyApplication.class, args);
@RequestMapping( path = "/hello-resource", method = RequestMethod.GET )
public String hello()
return "hello";
DummyApplication - application.yml
# Discovery Server Access
eureka:
client:
serviceUrl:
defaultZone: http://localhost:1111/discovery/eureka/
instance:
instanceId: $spring.application.name:$spring.application.instance_id:$random.value # Unique id for multiple instances
# HTTP Server
server:
port: 3333 # HTTP (Tomcat) port
context-path: /hello-context
DummyApplication - bootstrap.yml
# Spring properties
spring:
application:
name: hello-service # Service registers under this name
jmx:
default-domain: com.example.cloud.hello
encrypt:
failOnError: false
【问题讨论】:
您从客户端/浏览器调用什么 URL? GET localhost:1111/api/hello/hello/hello 是的,我知道,我只是喜欢问候......感谢您的快速回复! 【参考方案1】:我偶然发现...原来 server.port 的值需要与部署它的 Tomcat 实例的端口匹配。现在看起来很明显,但我认为 Spring 会以某种方式神奇地从它运行的容器中找出这一点。我想从外部位置读取该配置以处理不同的环境而不需要进行“代码更改”是个好主意.
无论如何,答案是:确保 application.yml 中的 server.port 与目标容器上的端口匹配。
感谢所有花时间帮助我的人!
【讨论】:
或者只使用嵌入式 TC 服务器从命令行运行 Spring Boot 应用程序。 是的,但这正是我要避免的。我想用尽可能少的 jvm 运行多个微服务【参考方案2】:好的,@SpringCloudApplication
包装 @EnableDiscoveryClient
导致 DummyApplication
在启动时向 Eureka 注册。您可以通过 Eureka 仪表板确认这是否正在发生。
假设DummyApplication
在 Eureka 注册为服务名称“hello-service”,那么 Zuul / Ribbon 将为该服务名称创建一个路由。因此,您的“/hello-resource”端点应该通过 Zuul 在以下位置代理:
http://localhost:4444/api/hello-service/hello-resource/
【讨论】:
感谢您的意见。请记住,Hello 应用程序部署在/hello-context/
下,因此 Zuul 端点看起来像 http://localhost:4444/api/hello-service/hello-context/hello-resource
【参考方案3】:
您应该将 Bowser 指向端口 4444(网关),而不是 1111(eureka)。
【讨论】:
我的错误.. 我在 1111 上的 tomcat 实例同时具有网关和尤里卡服务器。当我从 eclipse 运行所有东西时,我确实在 4444 上调用它 不过,我在您的示例中看不到第三个 /hello 。端口是 4444。第一个上下文路径是 /api,然后是来自网关的 /hello,然后是来自 REST 的 /hello。第三个 /hello 来自哪里?此外,尝试从 eureka 中删除 /discovery 以进行调试,然后只指向 ip/eureka。 我知道这有多令人困惑。我更新了我的配置,所以现在我的调用看起来像 localhost:port/api/hello-service/hello-context/hello-resource ..我也试过你的将 /discovery 移动到 ROOT 的建议,但不幸的是我仍然得到相同的行为以上是关于Spring Cloud 应用程序 - 在 Tomcat 上部署后 zuul 超时的主要内容,如果未能解决你的问题,请参考以下文章
如何在本地使用 spring-cloud-starter-aws 运行应用程序?
如何在 spring-cloud-gateway 合约测试中从 spring-cloud-contract 中设置带有 StubRunner 端口的 url