packagewebapp.conf;importcom.netflix.hystrix.HystrixThreadPoolKey;importcom.netflix.hystrix.HystrixThreadPoolProperties;importcom.netflix.hystrix.strategy.HystrixPlugins;importcom.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy;importcom.netflix.hystrix.strategy.concurrency.HystrixRequestVariable;importcom.netflix.hystrix.strategy.concurrency.HystrixRequestVariableLifecycle;importcom.netflix.hystrix.strategy.eventnotifier.HystrixEventNotifier;importcom.netflix.hystrix.strategy.executionhook.HystrixCommandExecutionHook;importcom.netflix.hystrix.strategy.metrics.HystrixMetricsPublisher;importcom.netflix.hystrix.strategy.properties.HystrixPropertiesStrategy;importcom.netflix.hystrix.strategy.properties.HystrixProperty;importfeign.RequestInterceptor;importfeign.RequestTemplate;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importorg.springframework.context.annotation.Bean;importorg.springframework.web.context.request.RequestAttributes;importorg.springframework.web.context.request.RequestContextHolder;importorg.springframework.web.context.request.ServletRequestAttributes;importjavax.servlet.http.HttpServletRequest;importjava.util.Enumeration;importjava.util.concurrent.BlockingQueue;importjava.util.concurrent.Callable;importjava.util.concurrent.ThreadPoolExecutor;importjava.util.concurrent.TimeUnit;public class FeignConfig implementsRequestInterceptor {
@BeanpublicFeignHystrixConcurrencyStrategy feignHystrixConcurrencyStrategy() {return newFeignHystrixConcurrencyStrategy();
}
@Overridepublic voidapply(RequestTemplate template) {
RequestAttributes requestAttributes=RequestContextHolder.getRequestAttributes();if (requestAttributes == null) {return;
}
HttpServletRequest request=((ServletRequestAttributes) requestAttributes).getRequest();
Enumeration headerNames =request.getHeaderNames();if (headerNames != null) {while(headerNames.hasMoreElements()) {
String name=headerNames.nextElement();
Enumeration values =request.getHeaders(name);while(values.hasMoreElements()) {
String value=values.nextElement();
template.header(name, value);
}
}
}
}
}class FeignHystrixConcurrencyStrategy extendsHystrixConcurrencyStrategy {private static final Logger log = LoggerFactory.getLogger(FeignHystrixConcurrencyStrategy.class);privateHystrixConcurrencyStrategy delegate;
FeignHystrixConcurrencyStrategy() {try{this.delegate =HystrixPlugins.getInstance().getConcurrencyStrategy();if (this.delegate instanceofFeignHystrixConcurrencyStrategy) {//Welcome to singleton hell...
return;
}
HystrixCommandExecutionHook commandExecutionHook=HystrixPlugins.getInstance().getCommandExecutionHook();
HystrixEventNotifier eventNotifier=HystrixPlugins.getInstance().getEventNotifier();
HystrixMetricsPublisher metricsPublisher=HystrixPlugins.getInstance().getMetricsPublisher();
HystrixPropertiesStrategy propertiesStrategy=HystrixPlugins.getInstance().getPropertiesStrategy();this.logCurrentStateOfHystrixPlugins(eventNotifier, metricsPublisher, propertiesStrategy);
HystrixPlugins.reset();
HystrixPlugins.getInstance().registerConcurrencyStrategy(this);
HystrixPlugins.getInstance().registerCommandExecutionHook(commandExecutionHook);
HystrixPlugins.getInstance().registerEventNotifier(eventNotifier);
HystrixPlugins.getInstance().registerMetricsPublisher(metricsPublisher);
HystrixPlugins.getInstance().registerPropertiesStrategy(propertiesStrategy);
}catch(Exception e) {
log.error("Failed to register Sleuth Hystrix Concurrency Strategy", e);
}
}private voidlogCurrentStateOfHystrixPlugins(HystrixEventNotifier eventNotifier,
HystrixMetricsPublisher metricsPublisher, HystrixPropertiesStrategy propertiesStrategy) {if(log.isDebugEnabled()) {
log.debug("Current Hystrix plugins configuration is [" + "concurrencyStrategy ["
+ this.delegate + "]," + "eventNotifier [" + eventNotifier + "]," + "metricPublisher ["
+ metricsPublisher + "]," + "propertiesStrategy [" + propertiesStrategy + "]," + "]");
log.debug("Registering Sleuth Hystrix Concurrency Strategy.");
}
}
@Overridepublic Callable wrapCallable(Callablecallable) {
RequestAttributes requestAttributes=RequestContextHolder.getRequestAttributes();return new WrappedCallable<>(callable, requestAttributes);
}
@OverridepublicThreadPoolExecutor getThreadPool(HystrixThreadPoolKey threadPoolKey,
HystrixProperty corePoolSize, HystrixPropertymaximumPoolSize,
HystrixProperty keepAliveTime, TimeUnit unit, BlockingQueueworkQueue) {return this.delegate.getThreadPool(threadPoolKey, corePoolSize, maximumPoolSize, keepAliveTime,
unit, workQueue);
}
@OverridepublicThreadPoolExecutor getThreadPool(HystrixThreadPoolKey threadPoolKey,
HystrixThreadPoolProperties threadPoolProperties) {return this.delegate.getThreadPool(threadPoolKey, threadPoolProperties);
}
@Overridepublic BlockingQueue getBlockingQueue(intmaxQueueSize) {return this.delegate.getBlockingQueue(maxQueueSize);
}
@Overridepublic HystrixRequestVariable getRequestVariable(HystrixRequestVariableLifecyclerv) {return this.delegate.getRequestVariable(rv);
}static class WrappedCallable implements Callable{private final Callabletarget;private finalRequestAttributes requestAttributes;
WrappedCallable(Callabletarget, RequestAttributes requestAttributes) {this.target =target;this.requestAttributes =requestAttributes;
}
@Overridepublic T call() throwsException {try{
RequestContextHolder.setRequestAttributes(requestAttributes);returntarget.call();
}finally{
RequestContextHolder.resetRequestAttributes();
}
}
}
}