Debugging timeouts may be tricky, considering there are 3 levels of routing alone (Zuul→Hystrix→Ribbon), not including async execution layers and the retry engine. The following scheme is valid for Spring Cloud releases Camden.SR6 and newer (I've checked this on Dalston.SR1):
Zuul routes the request through RibbonRoutingFilter
, which creates a Ribbon command with the request context. Ribbon command then creates a LoadBalancer command, which uses spring-retry for command execution, choosing retry policy for the RetryTemplate
according to Zuul settings. @EnableRetry
does nothing in this case, because this annotation enables wrapping methods with @Retryable
annotation in retrying proxies.
This means, your command duration is limited to the lesser value of these two (see this post):
- [
HystrixTimeout
], which is a timeout for invoked Hystrix command
- [
RibbonTimeout * MaxAutoRetries * MaxAutoRetriesNextServer
] (retries kick in only if Zuul has them enabled in its configuration), where [RibbonTimeout = ConnectTimeout + ReadTimeout
] on the http client.
For debugging, it's convenient to create a breakpoint in RetryableRibbonLoadBalancingHttpClient#executeWithRetry
or RetryableRibbonLoadBalancingHttpClient#execute
method. At this point, you have:
ContextAwareRequest
instance (e.g. RibbonApacheHttpRequest
or OkHttpRibbonRequest
) with request context, which containes Zuul's retryable
property;
LoadBalancedRetryPolicy
intsance with load balancer context, which contains Ribbon's maxAutoRetries
, maxAutoRetriesNextServer
and okToRetryOnAllOperations
properties;
RetryCallback
instance with a requestConfig, which contains HttpClient's connectTimeout
and socketTimeout
properties;
RetryTemplate
instance with chosen retry policy.
If the breakpoint is not hit, it means that org.springframework.cloud.netflix.ribbon.apache.RetryableRibbonLoadBalancingHttpClient
bean was not instantiated. This happenes when the spring-retry library is not in the classpath.