Zuul / Ribbon / Hystrix не повторяет попытку на другом экземпляре

фон

я использую Spring cloud Brixton.Алгоритм RC2, с Зуул и еврики.

у меня есть одна служба шлюза с @EnableZuulProxy и a book-service С status метод. Через конфигурацию я могу эмулировать работу на status способ спать определенное количество времени.

маршрут Зуул прост

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

я запускаю два экземпляра book-service. Когда я устанавливаю время сна ниже порога тайм-аута Hystrix (1000ms) , я вижу запросы переход к обоим экземплярам книжных сервисов. Это хорошо работает.

Я понимаю, что если команда Hystrix терпит неудачу, лента должна иметь возможность повторить команду на другом сервере. Это должно сделать ошибку прозрачной для клиента.

я прочитал конфигурацию ленты и добавил следующую конфигурацию в 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

теперь я обновляю конфигурацию так, что только одна служба спит более 1s, это значит, что у меня одна медицинская служба, и одна плохая.

когда я вызываю шлюзы, вызовы отправляются в оба экземпляра, и половина вызовов возвращает 500. В шлюзе я вижу тайм-аут Hystrix:

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

почему лента не повторяет вызов на другом экземпляре?

я что-то пропустил здесь?


ссылки

1 ответов


по умолчанию Zuul использует стратегию изоляции семафора, которая не позволяет установить тайм-аут. Я не могу использовать балансировку нагрузки с этим стратегия. Что сработало для меня (следуя вашему примеру):

1) Изменение изоляции Zuul в поток:

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

важно: timeoutInMilliseconds= 100000-это как сказать, что нет HystrixTimeout. Почему? Потому что, если Hystrix times out не будет балансировки нагрузки (я только что протестировал его, играя с timeoutInMilliseconds)

затем настройте ReadTimeout ленты на нужное значение:

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

в этом случае после истечения времени службы 1sec в ленте он повторит попытку с помощью службы 500ms

ниже у вас есть журнал, который я получил в своем экземпляре zuul:

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