第一次调用 ZuulException (SendErrorFilter)

Posted

技术标签:

【中文标题】第一次调用 ZuulException (SendErrorFilter)【英文标题】:ZuulException (SendErrorFilter) at first call 【发布时间】:2019-07-31 18:08:10 【问题描述】:

我正在通过 Spring Cloud、Spring Boot 和 Docker 构建应用程序。整个应用程序运行良好。我有几个微服务。每个项目都在 Docker 上运行。当我尝试通过 Zuul API Gateway 使用我的微服务时,我在第一次调用时遇到错误。但是如果我刷新浏览器它工作正常。错误如下--

2019-03-10 04:54:55.440  WARN [netflix- 
zuul-api-gateway- 
server,1855093598d4f99c,1855093598d4f99c
true] 1 --- [nio-8765-exec-1] 
o.s.c.n.z.filters.post.SendErrorFilter   
: Error during filtering


com.netflix.zuul.exception.ZuulException 
at 
org.springframework.cloud.netflix.zuul.
filters.post.SendErrorFilter.
findZuulException(SendErrorFilter.java:
114) ~[spring-cloud-netflix-zuul- 
2.1.0.RC3.jar!/:2.1.0.RC3]
at 
org.springframework.cloud.netflix.zuul.
filters.post.SendErrorFilter.run
(SendErrorFilter.java:76) ~[spring- 
cloud- 
netflix-zuul-2.1.0.RC3.jar!/
:2.1.0.RC3]
at 
com.netflix.zuul.ZuulFilter.runFilter
(ZuulFilter.java:117) [zuul-core- 
1.3.1.jar!/:1.3.1]
at 
com.netflix.zuul.FilterProcessor.
processZuulFilter(FilterProcessor.
java:193) [zuul-core-1.3.1.jar!/:1.3.1]
 at 
com.netflix.zuul.FilterProcessor.
runFilters(FilterProcessor.java:157) 
[zuul-core-1.3.1.jar!/:1.3.1]
at 
com.netflix.zuul.FilterProcessor.error
(FilterProcessor.java:105) [zuul-core- 
1.3.1.jar!/:1.3.1]
at com.netflix.zuul.ZuulRunner.error
(ZuulRunner.java:112) [zuul-core- 
1.3.1.jar!/:1.3.1]
at 
com.netflix.zuul.http.ZuulServlet.error
(ZuulServlet.java:145) [zuul-core- 
1.3.1.jar!/:1.3.1]
at 
com.netflix.zuul.http.ZuulServlet.servic
e(ZuulServlet.java:83) [zuul-core- 
1.3.1.jar!/:1.3.1]
at org.springframework.web.servlet.mvc.
Servlet 
letWrappingController.java:165) [spring- 
webmvc- 
5.1.3.RELEASE.jar!/:5.1.3.RELEASE]
at org.spr

我已经为我的所有项目创建了图像。并将其推送到 DockerHub 中。而 Docker-Compose 文件我也推送到了 GitHub 中。下面是路径。

https://github.com/numery009/DockerCompose/blob/master/docker-compose.yaml

我还将它部署在 EC2 上的 Docker Swarm 上。 但是当我尝试通过 Zuul 使用我的微服务时,它根本不起作用。而且我的每个请求都会收到相同的“过滤器错误”。

请帮忙!!!。

【问题讨论】:

请尝试以下 URL 获取 Docker-Compose 文件github.com/numery009/Docker-Compose/blob/master/… 这是不是只要你用 docker-compose 启动应用程序就会发生这种情况,然后它就可以正常工作了吗? 这是通过 Zuul 的第一个请求发生的。我在本地机器上尝试了 Docker-Compose。对于第一个请求,我收到了错误。然后,如果我刷新浏览器它工作正常。我还在 EC2 上尝试了 Docker-Swarm。每次在 EC2 上遇到相同的过滤器错误。对于 EC2,它不起作用。我需要更改任何代码吗? 在通过 zuul 发送任何请求之前,我已经检查了所有服务日志。我不会立即发送请求。当我的所有服务都启动并运行时,我又给了 5 分钟时间来预热 docker。我关心的基本上是EC2。每次在 EC2 上我都遇到同样的错误。我可以按照哪些步骤来解决它? 点击以下 URL 并检查 Zuul 容器上的日志,您可以看到错误。 localhost:8765/customer-account-mysql/api/v1/customer-feign 【参考方案1】:

将 URL 从 localhost 更改为发现客户端中提到的服务名称。

【讨论】:

【参考方案2】:

对于通过 Zuul 的请求,我们需要牢记三件事

1) 根据本文档 - https://cloud.spring.io/spring-cloud-static/spring-cloud-netflix/1.4.3.RELEASE/single/spring-cloud-netflix.html#_zuul_eager_application_context_loading

Zuul 内部使用 Ribbon 来调用远程 url,默认情况下,Ribbon 客户端在第一次调用时由 Spring Cloud 延迟加载。可以使用以下配置为 Zuul 更改此行为,这将导致子 Ribbon 相关的应用程序上下文在应用程序启动时被急切地加载。

应用程序.yaml

zuul:
   ribbon:
      eager-load:
         enabled: true

application.properties

zuul.ribbon.eager-load.enabled= true

2) 根据本文档 - http://cloud.spring.io/spring-cloud-static/Edgware.SR3/single/spring-cloud.html#_service_discovery_configuration

服务发现配置 --- 如果 Zuul 使用服务发现,则需要关注两个超时,Hystrix 超时(因为默认情况下所有路由都包装在 Hystrix 命令中)和 Ribbon 超时。 Hystrix 超时需要考虑功能区读取和连接超时加上该服务将发生的重试总数。默认情况下,Spring Cloud Zuul 会尽力为您计算 Hystrix 超时,除非您明确指定 Hystrix 超时。

Hystrix 超时使用以下公式计算:

(ribbon.ConnectTimeout + ribbon.ReadTimeout) * (ribbon.MaxAutoRetries + 1) * 
(ribbon.MaxAutoRetriesNextServer + 1)

例如,如果您在应用程序属性中设置以下属性

应用程序.yaml

ribbon:
   ReadTimeout:100
   ConnectTimeout:500
   MaxAutoRetries:1
   MaxAutoRetriesNextServer:1

application.properties

ribbon.ReadTimeout= 100
ribbon.ConnectTimeout= 500
ribbon.MaxAutoRetries= 1
ribbon.MaxAutoRetriesNextServer= 1

然后Hystrix超时(在这种情况下所有路由)将设置为2400ms。


在我的 zuul 应用程序配置中,我添加了以下属性。它适用于我的第一个电话,没有任何错误。

应用程序.yaml

hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 11000

ribbon:
   ConnectTimeout: 10000
   ReadTimeout: 10000

application.properties

hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds= 11000

ribbon.ConnectTimeout= 10000
ribbon.ReadTimeout: 10000

3) 这是最简单的方法。禁用hystrix执行超时。

根据本文档-https://github.com/Netflix/Hystrix/wiki/Configuration#executiontimeoutenabled

以下属性将禁用 Zuul 上的 hystrix 执行超时

application.properties

hystrix.command.default.execution.timeout.enabled=false

如果我们记住这3个场景,那么我们很容易得到ZuulException(SendErrorFilter)的解决方案。

【讨论】:

【参考方案3】:

根据this documentation:

Zuul 在内部使用 Ribbon 来调用远程 URL。默认情况下,Spring Cloud 在第一次调用时会延迟加载 Ribbon 客户端。可以使用以下配置为 Zuul 更改此行为,这会导致在应用程序启动时预先加载与子 Ribbon 相关的应用程序上下文。

以下示例显示了如何启用预加载:

# application.yml
zuul:
  ribbon:
    eager-load:
      enabled: true

或者

# application.properties
ribbon.eager-load.enabled = true

您可能需要检查以下相关问题:

Ryan Baxter's comment First request through Zuul/Euruka will always timeout. Subsequent requests then behave as expected (no timeouts)

【讨论】:

它对我不起作用。我已经使用了这个属性。但仍然出现同样的错误。

以上是关于第一次调用 ZuulException (SendErrorFilter)的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot 微服务 com.netflix.zuul.exception.ZuulException:转发错误

解决ZuulException: Forwarding error以及Readed time out

如何修复 ZuulException:转发错误

多次调用 send() 合并为一次调用 recv()

com.netflix.zuul.exception.ZuulException:Hystrix 读取超时

如何为 ZuulException 自定义 Spring Boot 控制器 API 响应