Skip to content

Instantly share code, notes, and snippets.

@ryanjbaxter
Last active September 12, 2016 18:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ryanjbaxter/da3663ffb98d0b10c67a6bb82aae590c to your computer and use it in GitHub Desktop.
Save ryanjbaxter/da3663ffb98d0b10c67a6bb82aae590c to your computer and use it in GitHub Desktop.
Custom Ribbon RestClient class
package com.ryanjbaxter.spring.cloud.ocr.web;
import com.netflix.client.RequestSpecificRetryHandler;
import com.netflix.client.config.CommonClientConfigKey;
import com.netflix.client.config.IClientConfig;
import com.netflix.client.http.HttpRequest;
import com.netflix.client.http.HttpResponse;
import com.netflix.loadbalancer.Server;
import com.netflix.niws.client.http.RestClient;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.client.apache4.ApacheHttpClient4;
import org.springframework.cloud.netflix.ribbon.RibbonUtils;
import org.springframework.cloud.netflix.ribbon.ServerIntrospector;
import java.net.URI;
/* Most of this code comes from RibbonClientConfiguration.OverrideRestClient but we can't extend
* that class directly. the only custom code here is in the execute method. In addition
* getRequestSpecificRetryHandler returns a cusomt RetryHandler, however the logic in this
* method is the same as what is in RibbonClientConfiguration.
*/
public class MyRestClient extends RestClient {
private IClientConfig config;
private ServerIntrospector serverIntrospector;
public MyRestClient(IClientConfig config, ServerIntrospector serverIntrospector) {
this.config = config;
this.serverIntrospector = serverIntrospector;
this.initWithNiwsConfig(this.config);
}
public URI reconstructURIWithServer(Server server, URI original) {
URI uri = RibbonUtils.updateToHttpsIfNeeded(original, this.config, this.serverIntrospector, server);
return super.reconstructURIWithServer(server, uri);
}
protected Client apacheHttpClientSpecificInitialization() {
ApacheHttpClient4 apache = (ApacheHttpClient4)super.apacheHttpClientSpecificInitialization();
apache.getClientHandler().getHttpClient().getParams().setParameter("http.protocol.cookie-policy", "ignoreCookies");
return apache;
}
@Override
public HttpResponse execute(HttpRequest task, IClientConfig requestConfig) throws Exception {
HttpResponse superResponse = super.execute(task, requestConfig);
if(superResponse.getStatus() >= 500) {
throw new ServiceException("downstream service instance encountored a problem");
} else {
return superResponse;
}
}
@Override
public RequestSpecificRetryHandler getRequestSpecificRetryHandler(HttpRequest request, IClientConfig requestConfig) {
if (!request.isRetriable()) {
return new MyRetryHandler(false, false, this.getRetryHandler(), requestConfig);
}
if (this.config.get(CommonClientConfigKey.OkToRetryOnAllOperations, false)) {
return new RequestSpecificRetryHandler(true, true, this.getRetryHandler(), requestConfig);
}
if (request.getVerb() != HttpRequest.Verb.GET) {
return new MyRetryHandler(true, false, this.getRetryHandler(), requestConfig);
} else {
return new MyRetryHandler(true, true, this.getRetryHandler(), requestConfig);
}
}
static class ServiceException extends RuntimeException {
public ServiceException(String reason) {
super(reason);
}
}
}
package com.ryanjbaxter.spring.cloud.ocr.web;
import com.netflix.client.RequestSpecificRetryHandler;
import com.netflix.client.RetryHandler;
import com.netflix.client.config.IClientConfig;
public class MyRetryHandler extends RequestSpecificRetryHandler {
public MyRetryHandler(boolean okToRetryOnConnectErrors, boolean okToRetryOnAllErrors) {
super(okToRetryOnConnectErrors, okToRetryOnAllErrors);
}
public MyRetryHandler(boolean okToRetryOnConnectErrors, boolean okToRetryOnAllErrors, RetryHandler baseRetryHandler, IClientConfig requestConfig) {
super(okToRetryOnConnectErrors, okToRetryOnAllErrors, baseRetryHandler, requestConfig);
}
@Override
public boolean isRetriableException(Throwable e, boolean sameServer) {
if(e instanceof MyRestClient.ServiceException) {
return true;
}
return super.isRetriableException(e, sameServer);
}
}
package com.ryanjbaxter.spring.cloud.ocr.web.exclude;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cloud.netflix.ribbon.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.netflix.client.DefaultLoadBalancerRetryHandler;
import com.netflix.client.RetryHandler;
import com.netflix.client.config.DefaultClientConfigImpl;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.*;
import com.netflix.niws.client.http.RestClient;
import com.netflix.servo.monitor.Monitors;
import com.ryanjbaxter.spring.cloud.ocr.web.MyRestClient;
@Configuration
public class MyRibbonConfiguration {
@Value("${ribbon.client.name}")
private String name = "client";
@Bean
public RestClient ribbonRestClient(IClientConfig config, ILoadBalancer loadBalancer, ServerIntrospector serverIntrospector, RetryHandler retryHandler) {
MyRestClient client = new MyRestClient(config, serverIntrospector);
client.setLoadBalancer(loadBalancer);
client.setRetryHandler(retryHandler);
Monitors.registerObject("Client_" + name, client);
return client;
}
}
@Configuration
@EnableAutoConfiguration
@EnableDiscoveryClient
@EnableZuulProxy
@RibbonClients(defaultConfiguration = MyRibbonConfiguration.class)
@ComponentScan(basePackages = "com.ryanjbaxter.spring.cloud.ocr.web",
excludeFilters =@ComponentScan.Filter(
type = FilterType.REGEX,
pattern = "com.ryanjbaxter.spring.cloud.ocr.web.exclude.*"))
public class OcrWebApplication {
public static void main(String[] args) {
SpringApplication.run(OcrWebApplication.class, args);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment