Zuul/Ribbon/Hystrix不在其他实例上重试 [英] Zuul/Ribbon/Hystrix not retrying on different instance

查看:381
本文介绍了Zuul/Ribbon/Hystrix不在其他实例上重试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在与Zuul和Eureka一起使用Spring cloud Brixton.RC2.

I'm using Spring cloud Brixton.RC2, with Zuul and Eureka.

我有一个带有@EnableZuulProxy的网关服务和一个带有status方法的book-service.通过配置,我可以通过休眠一段预定的时间来模拟status方法上的工作.

I have one gateway service with @EnableZuulProxy and a book-service with a status method. Via configuration I can emulate work on the status method by sleeping a defined amount of time.

Zuul路线很简单

zuul.routes.foos.path=/foos/**
zuul.routes.foos.serviceId=reservation-service

我运行book-service的两个实例.当我将休眠时间设置为低于Hystrix超时阈值(1000毫秒)时,我可以看到请求同时进入了两个图书服务实例.效果很好.

I run two instances of the book-service. When I set the sleeping time below the Hystrix timeout threshold (1000ms) I can see requests going to both instance of the book services. This works well.

我知道,如果Hystrix命令失败,Ribbon应该可以在其他服务器上重试该命令.这应该使故障对客户端透明.

I understand that if the Hystrix command fails, it should be possible for Ribbon to retry the command on a different server. This should make the failure transparent to the client.

我阅读了Ribbon配置并在Zuul中添加了以下配置:

I read the Ribbon configuration and added the following configuration in Zuul:

zuul.routes.reservation-service.retryable=true //not sure which one to try
zuul.routes.foos.retryable=true //not sure which one to try

ribbon.MaxAutoRetries=0 // I don't want to retry on the same host, I also tried with 1 it doesn't work either
ribbon.MaxAutoRetriesNextServer=2
ribbon.OkToRetryOnAllOperations=true

现在,我更新配置,以便只有一项服务的睡眠时间超过1秒,这意味着我拥有一项健康服务,而一项不良服务.

Now I update the configuration so that only one service sleeps for more than 1s, which means that I have one health service, and one bad one.

当我呼叫网关时,呼叫将发送到两个实例,一半的呼​​叫返回500.在网关中,我看到Hystrix超时:

When I call the gateways the calls get send to both instances, and half the calls returns a 500. In the gateway I see the Hystrix timeout:

com.netflix.zuul.exception.ZuulException: Forwarding error
    [...]
Caused by: com.netflix.hystrix.exception.HystrixRuntimeException: reservation-service timed-out and no fallback available.
    [...]
Caused by: java.util.concurrent.TimeoutException: null

功能区为什么不重试其他实例上的呼叫?

Why isn't Ribbon retrying the call on the other instance?

我在这里错过什么吗?

Am I Missing something here?

  • 与此问题相关的问题(未解决)
  • 功能区配置
  • 根据此提交 Zuul应该支持以下重试丝带
  • Relates to this question (not solved)
  • Ribbon configuration
  • According to this commit Zuul should support retries for Ribbon

推荐答案

默认情况下,Zuul使用SEMAPHORE隔离策略,该策略不允许设置超时.我无法在这种策略下使用负载平衡.对我有用的是(按照您的示例):

By default Zuul uses SEMAPHORE isolation strategy which doesn't allow to set a timeout. I haven't been able to use load balancing with this stragegy. What worked for me was (following your example):

1)将Zuul的隔离更改为THREAD:

1) Changing Zuul's isolation to THREAD:

hystrix:
  command:
    reservation-service:
      execution:
        isolation:
          strategy: THREAD
          thread:
            timeoutInMilliseconds: 100000

重要:timeoutInMilliseconds = 100000就像说没有HystrixTimeout.为什么?因为如果Hystrix超时,就不会有任何负载平衡(我只是用timeoutInMilliseconds测试了它)

IMPORTANT: timeoutInMilliseconds= 100000 is like saying no HystrixTimeout. Why? Because if Hystrix times out there won't be any load balancing (I just tested it playing with timeoutInMilliseconds)

然后,将Ribbon的ReadTimeout配置为所需的值:

Then, configure Ribbon's ReadTimeout to the desired value:

reservation-service:
  ribbon:
    ReadTimeout: 800
    ConnectTimeout: 250
    OkToRetryOnAllOperations: true
    MaxAutoRetriesNextServer: 2
    MaxAutoRetries: 0

在这种情况下,Ribbon中的1秒服务超时后,它将使用500ms服务重试

In this case after the 1sec service times out in Ribbon it'll retry with the 500ms service

下面有我在zuul实例中获得的日志:

Below you have the log I got in my zuul instance:

o.s.web.servlet.DispatcherServlet        : DispatcherServlet with name 'dispatcherServlet' processing GET request for [/api/stories]
o.s.web.servlet.DispatcherServlet        : Last-Modified value for [/api/stories] is: -1
c.n.zuul.http.HttpServletRequestWrapper  : Path = null
c.n.zuul.http.HttpServletRequestWrapper  : Transfer-Encoding = null
c.n.zuul.http.HttpServletRequestWrapper  : Content-Encoding = null
c.n.zuul.http.HttpServletRequestWrapper  : Content-Length header = -1
c.n.loadbalancer.ZoneAwareLoadBalancer   : Zone aware logic disabled or there is only one zone
c.n.loadbalancer.LoadBalancerContext     : storyteller-api using LB returned Server: localhost:7799 for request /api/stories

---> ATTEMPTING THE SLOW SERVICE

com.netflix.niws.client.http.RestClient  : RestClient sending new Request(GET: ) http://localhost:7799/api/stories
c.n.http4.MonitoredConnectionManager     : Get connection: {}->http://localhost:7799, timeout = 250
com.netflix.http4.NamedConnectionPool    : [{}->http://localhost:7799] total kept alive: 1, total issued: 0, total allocated: 1 out of 200
com.netflix.http4.NamedConnectionPool    : No free connections [{}->http://localhost:7799][null]
com.netflix.http4.NamedConnectionPool    : Available capacity: 50 out of 50 [{}->http://localhost:7799][null]
com.netflix.http4.NamedConnectionPool    : Creating new connection [{}->http://localhost:7799]
com.netflix.http4.NFHttpClient           : Attempt 1 to execute request
com.netflix.http4.NFHttpClient           : Closing the connection.
c.n.http4.MonitoredConnectionManager     : Released connection is not reusable.
com.netflix.http4.NamedConnectionPool    : Releasing connection [{}->http://localhost:7799][null]
com.netflix.http4.NamedConnectionPool    : Notifying no-one, there are no waiting threads

--- HERE'S RIBBON'S TIMEOUT

c.n.l.reactive.LoadBalancerCommand       : Got error com.sun.jersey.api.client.ClientHandlerException: java.net.SocketTimeoutException: Read timed out when executed on server localhost:7799
c.n.loadbalancer.ZoneAwareLoadBalancer   : Zone aware logic disabled or there is only one zone
c.n.loadbalancer.LoadBalancerContext     : storyteller-api using LB returned Server: localhost:9977 for request /api/stories

---> HERE IT RETRIES

com.netflix.niws.client.http.RestClient  : RestClient sending new Request(GET: ) http://localhost:9977/api/stories
c.n.http4.MonitoredConnectionManager     : Get connection: {}->http://localhost:9977, timeout = 250
com.netflix.http4.NamedConnectionPool    : [{}->http://localhost:9977] total kept alive: 1, total issued: 0, total allocated: 1 out of 200
com.netflix.http4.NamedConnectionPool    : Getting free connection [{}->http://localhost:9977][null]
com.netflix.http4.NFHttpClient           : Stale connection check
com.netflix.http4.NFHttpClient           : Attempt 1 to execute request
com.netflix.http4.NFHttpClient           : Connection can be kept alive indefinitely
c.n.http4.MonitoredConnectionManager     : Released connection is reusable.
com.netflix.http4.NamedConnectionPool    : Releasing connection [{}->http://localhost:9977][null]
com.netflix.http4.NamedConnectionPool    : Pooling connection [{}->http://localhost:9977][null]; keep alive indefinitely
com.netflix.http4.NamedConnectionPool    : Notifying no-one, there are no waiting threads
o.s.web.servlet.DispatcherServlet        : Null ModelAndView returned to DispatcherServlet with name 'dispatcherServlet': assuming HandlerAdapter completed request handling
o.s.web.servlet.DispatcherServlet        : Successfully completed request
o.s.web.servlet.DispatcherServlet        : DispatcherServlet with name 'dispatcherServlet' processing GET request for [/favicon.ico]
o.s.w.s.handler.SimpleUrlHandlerMapping  : Matching patterns for request [/favicon.ico] are [/**/favicon.ico]
o.s.w.s.handler.SimpleUrlHandlerMapping  : URI Template variables for request [/favicon.ico] are {}
o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapping [/favicon.ico] to HandlerExecutionChain with handler [ResourceHttpRequestHandler [locations=[ServletContext resource [/], class path resource [META-INF/resources/], class path resource [resources/], class path resource [static/], class path resource [public/], class path resource []], resolvers=[org.springframework.web.servlet.resource.PathResourceResolver@a0d875d]]] and 1 interceptor
o.s.web.servlet.DispatcherServlet        : Last-Modified value for [/favicon.ico] is: -1
o.s.web.servlet.DispatcherServlet        : Null ModelAndView returned to DispatcherServlet with name 'dispatcherServlet': assuming HandlerAdapter completed request handling
o.s.web.servlet.DispatcherServlet        : Successfully completed request

这篇关于Zuul/Ribbon/Hystrix不在其他实例上重试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆