Automatic retry with Ribbon (no zuul): not working + wrong documentation?
In the latest version of the official Spring Cloud Netflix documentation (e.g. 2.0.2. RELEASE, the last GA version).
When Spring Retry is present, load-balanced RestTemplates, Feign, and Zuul automatically retry any failed requests (assuming your configuration allows doing so).
But the use of independent ribbons (that is, load-balanced RestTemplates) seems wrong. I can’t get it to work and I can’t find any working examples. In addition, I found that other sources say the opposite, such as:
- spring-cloud with RestTemplate//Ribbon/Eureka – retry when server not available
- Spring Cloud – Getting Retry Working In RestTemplate? ).
So, is it a documentation error or is the whole world missing something?
Solution
We found the same issue; Zuul neither retries nor fails over to an alternate server in the list of ribbon servers using the default (Apache Http client) configuration. We tracked down to this line of code in the RibbonLoadBalancingHttpClient
class:
@Override
public RequestSpecificRetryHandler getRequestSpecificRetryHandler(
RibbonApacheHttpRequest request, IClientConfig requestConfig) {
return new RequestSpecificRetryHandler(false, false, RetryHandler.DEFAULT,
requestConfig);
}
Hard-coded false, false
parameters effectively prevent retries from occurring. It’s easy to solve this problem.
Add this to your Zuul main application class:
@RibbonClients(
defaultConfiguration = {EurekaRibbonClientConfiguration.class,
MyRibbonConfiguration.class})
Create a class MyRibbonConfiguration
and use it to emulate the ribbonLoadBalancingHttpClient
method here except that we overridden and fixed the getRequestSpecificRetryHandler
method that caused the problem.
public class MyRibbonConfiguration {
@RibbonClientName
private String name = "client";
@Bean
public RibbonLoadBalancingHttpClient ribbonLoadBalancingHttpClient(
IClientConfig config, ServerIntrospector serverIntrospector,
ILoadBalancer loadBalancer, RetryHandler retryHandler, CloseableHttpClient httpClient) {
RibbonLoadBalancingHttpClient client =
new RibbonLoadBalancingHttpClient(httpClient, config, serverIntrospector) {
@Override
public RequestSpecificRetryHandler getRequestSpecificRetryHandler(
RibbonApacheHttpRequest request, IClientConfig requestConfig) {
return new RequestSpecificRetryHandler(true, true, RetryHandler.DEFAULT,
requestConfig);
}
};
client.setLoadBalancer(loadBalancer);
client.setRetryHandler(retryHandler);
Monitors.registerObject("Client_" + this.name, client);
return client;
}
}
If needed, adjust true, true
to reference from the property. With this, Zuul will start complying with the ribbon. MaxAutoRetries
and ribbon. MaxAutoRetriesNextServer
property.
Note that if you use ribbon with Feign for server-> server calls, those Feign calls are not affected because OpenFeign hardcodes these two parameters to true, true
.