Spring 云应用程序 - 在 Tomcat 上部署后 zuul 超时

Spring Cloud app - zuul timeout after deploying on Tomcat

我正在尝试使用 Spring 云设置几个服务,在我将 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 实例用于发现和网关服务,还有第二个 Tomcat 实例用于 Eureka 客户端服务。

这是一些代码和配置..

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);
    }
}

网关应用程序 - 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

网关应用程序 - bootstrap.yml

# Spring properties
spring:
  application:
    name: gateway-service  # Identify this application
  jmx: 
    default-domain: com.example.cloud.gateway

encrypt:
  failOnError: false

DummyApplication

@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

您应该将浏览器指向端口 4444(网关),而不是 1111(尤里卡)。

好的,@SpringCloudApplication 包装了 @EnableDiscoveryClient,这导致 DummyApplication 在启动时向 Eureka 注册自己。您可以通过 Eureka 仪表板确认这种情况正在发生。

假设DummyApplication作为服务名"hello-service"向Eureka注册,那么Zuul/Ribbon会为那个服务名创建一个路由。因此,您的“/hello-resource”端点应该通过 Zuul 在以下位置进行代理: http://localhost:4444/api/hello-service/hello-resource/

一不小心想出来了...原来server.port的值需要和它部署的Tomcat实例的端口相匹配。现在看起来很明显,但我认为 Spring 会以某种方式神奇地从它所在的容器中找出它 运行 。我想从外部位置读取该配置以处理不同的环境是个好主意无需制作 'code changes'.

所以无论如何,答案是:确保 application.yml 中的 server.port 与目标容器上的端口相匹配。

感谢所有花时间帮助我的人!