Zuul / Ribbon / Hystrix do not repeat in different instances

Background

I am using Spring Cloud Brixton.RC2, with Zuul and Eureka.

I have a gateway service with @EnableZuulProxy and book-service using the status method. Through the configuration, I can emulate the work on the status method, sleeping for a certain amount of time.

Zuul's path is simple

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

I am running two instances of book-service . When I set the sleep time below the Hystrix timeout threshold (1000 ms), I can see the requests going as an instance of book services. It works well.

Problem

I understand that if the Hystrix command fails, Ribbon must retry the command on another server. This should make the failure transparent to the client.

I read the tape configuration and added the following configuration to 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 

Now I am updating the configuration so that only one service falls asleep for more than 1 second, which means that I have one health service and one bad one.

When I call the gateways, the calls are sent to both instances, and half the calls return 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 doesn't the tape repeat calling another instance?

Did I miss something here?


References

+6
source share
1 answer

By default, Zuul uses the SEMAPHORE isolation strategy, which does not allow a timeout. I could not use load balancing with this guard. What worked for me (after your example):

1) Changing Zuul's isolation to THREAD:

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

IMPORTANT : timeoutInMilliseconds = 100000 - this is not to say HystrixTimeout. What for? Because if the Hystrix time is out, there will be no load balancing (I just tested it while playing with the InMilliseconds timeout)

Then set Ribbon ReadTimeout to the desired value:

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

In this case, after the expiration of the service life of 1 sec in the tape, he will retry using the service 500 ms

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

 osweb.servlet.DispatcherServlet : DispatcherServlet with name 'dispatcherServlet' processing GET request for [/api/stories] osweb.servlet.DispatcherServlet : Last-Modified value for [/api/stories] is: -1 cnzuul.http.HttpServletRequestWrapper : Path = null cnzuul.http.HttpServletRequestWrapper : Transfer-Encoding = null cnzuul.http.HttpServletRequestWrapper : Content-Encoding = null cnzuul.http.HttpServletRequestWrapper : Content-Length header = -1 cnloadbalancer.ZoneAwareLoadBalancer : Zone aware logic disabled or there is only one zone cnloadbalancer.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 cnhttp4.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. cnhttp4.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 RIBBON TIMEOUT cnlreactive.LoadBalancerCommand : Got error com.sun.jersey.api.client.ClientHandlerException: java.net.SocketTimeoutException: Read timed out when executed on server localhost:7799 cnloadbalancer.ZoneAwareLoadBalancer : Zone aware logic disabled or there is only one zone cnloadbalancer.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 cnhttp4.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 cnhttp4.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 osweb.servlet.DispatcherServlet : Null ModelAndView returned to DispatcherServlet with name 'dispatcherServlet': assuming HandlerAdapter completed request handling osweb.servlet.DispatcherServlet : Successfully completed request osweb.servlet.DispatcherServlet : DispatcherServlet with name 'dispatcherServlet' processing GET request for [/favicon.ico] oswshandler.SimpleUrlHandlerMapping : Matching patterns for request [/favicon.ico] are [/**/favicon.ico] oswshandler.SimpleUrlHandlerMapping : URI Template variables for request [/favicon.ico] are {} oswshandler.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@a0 d875d]]] and 1 interceptor osweb.servlet.DispatcherServlet : Last-Modified value for [/favicon.ico] is: -1 osweb.servlet.DispatcherServlet : Null ModelAndView returned to DispatcherServlet with name 'dispatcherServlet': assuming HandlerAdapter completed request handling osweb.servlet.DispatcherServlet : Successfully completed request 
+3
source

All Articles