Hystrix 底层用了线程池,要传递ThreadLocal 数据,需要对HystrixConcurrencyStrategy 进行扩展
import com.netflix.hystrix.strategy.HystrixPlugins;
import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy;
import com.netflix.hystrix.strategy.eventnotifier.HystrixEventNotifier;
import com.netflix.hystrix.strategy.executionhook.HystrixCommandExecutionHook;
import com.netflix.hystrix.strategy.metrics.HystrixMetricsPublisher;
import com.netflix.hystrix.strategy.properties.HystrixPropertiesStrategy;
import com.gray.utils.GrayContextUtil;
import org.springframework.web.context.request.RequestContextHolder;
import java.util.Map;
import java.util.concurrent.Callable;
public class RequestHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy {
private HystrixConcurrencyStrategy hystrixConcurrencyStrategy;
public RequestHystrixConcurrencyStrategy() {
HystrixPlugins hystrixPlugins = HystrixPlugins.getInstance();
//当前策略
HystrixConcurrencyStrategy strategy = hystrixPlugins.getConcurrencyStrategy();
this.hystrixConcurrencyStrategy = strategy;
HystrixEventNotifier hystrixEventNotifier = hystrixPlugins.getEventNotifier();
HystrixCommandExecutionHook hystrixCommandExecutionHook = hystrixPlugins.getCommandExecutionHook();
HystrixMetricsPublisher hystrixMetricsPublisher = hystrixPlugins.getMetricsPublisher();
HystrixPropertiesStrategy hystrixPropertiesStrategy = hystrixPlugins.getPropertiesStrategy();
HystrixPlugins.reset();
//包装一层,在重新设置
hystrixPlugins.registerConcurrencyStrategy(this);
hystrixPlugins.registerEventNotifier(hystrixEventNotifier);
hystrixPlugins.registerCommandExecutionHook(hystrixCommandExecutionHook);
hystrixPlugins.registerMetricsPublisher(hystrixMetricsPublisher);
hystrixPlugins.registerPropertiesStrategy(hystrixPropertiesStrategy);
}
@Override
public <T> Callable<T> wrapCallable(Callable<T> callable) {
if (hystrixConcurrencyStrategy != null){
callable = hystrixConcurrencyStrategy.wrapCallable(callable);
}
return new WrappedCallable(callable, GrayContextUtil.getValues());
}
static class WrappedCallable<T> implements Callable<T> {
private final Callable<T> target;
private final Map<String,String> dataMap;
public WrappedCallable(Callable<T> target,Map<String,String> dataMap) {
this.target = target;
this.dataMap = dataMap;
}
@Override
public T call() throws Exception {
try {
//threadLocal数据传递
GrayContextUtil.setValues(dataMap);
return target.call();
} finally {
RequestContextHolder.resetRequestAttributes();
}
}
}
}