-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Description
在项目里使用了@HystrixCommand会导致ThreadLocal 为null。而我们使用的是THREAD隔离策略。网上搜索也知道了原因,可以参考这篇博文。
但是最终他的处理办法不推荐,在调试和看spring-security-core的 org.springframework.cloud.netflix.hystrix.security.SecurityContextConcurrencyStrategy和org.springframework.security.concurrent.DelegatingSecurityContextCallable给了我们解决办法。
添加以下类即可解决问题
@Configuration
public class ApiHystrixConfig {
@Autowired(required = false)
private HystrixConcurrencyStrategy existingConcurrencyStrategy;
@PostConstruct
public void init() {
// Keeps references of existing Hystrix plugins. 保留现有Hystrix插件。
HystrixEventNotifier eventNotifier = HystrixPlugins.getInstance()
.getEventNotifier();
HystrixMetricsPublisher metricsPublisher = HystrixPlugins.getInstance()
.getMetricsPublisher();
HystrixPropertiesStrategy propertiesStrategy = HystrixPlugins.getInstance()
.getPropertiesStrategy();
HystrixCommandExecutionHook commandExecutionHook = HystrixPlugins.getInstance()
.getCommandExecutionHook();
HystrixPlugins.reset();
// Registers existing plugins excepts the Concurrent Strategy plugin. 注册除Concurrent Strategy插件之外的现有插件。
HystrixPlugins.getInstance().registerConcurrencyStrategy(
new ApiContextConcurrencyStrategy(existingConcurrencyStrategy));
HystrixPlugins.getInstance().registerEventNotifier(eventNotifier);
HystrixPlugins.getInstance().registerMetricsPublisher(metricsPublisher);
HystrixPlugins.getInstance().registerPropertiesStrategy(propertiesStrategy);
HystrixPlugins.getInstance().registerCommandExecutionHook(commandExecutionHook);
}
class ApiContextConcurrencyStrategy extends HystrixConcurrencyStrategy {
private HystrixConcurrencyStrategy existingConcurrencyStrategy;
public ApiContextConcurrencyStrategy(HystrixConcurrencyStrategy existingConcurrencyStrategy) {
this.existingConcurrencyStrategy = existingConcurrencyStrategy;
}
@Override
public BlockingQueue<Runnable> getBlockingQueue(int maxQueueSize) {
return existingConcurrencyStrategy != null
? existingConcurrencyStrategy.getBlockingQueue(maxQueueSize)
: super.getBlockingQueue(maxQueueSize);
}
@Override
public <T> HystrixRequestVariable<T> getRequestVariable(HystrixRequestVariableLifecycle<T> rv) {
return existingConcurrencyStrategy != null
? existingConcurrencyStrategy.getRequestVariable(rv)
: super.getRequestVariable(rv);
}
@Override
public ThreadPoolExecutor getThreadPool(HystrixThreadPoolKey threadPoolKey,
HystrixProperty<Integer> corePoolSize,
HystrixProperty<Integer> maximumPoolSize,
HystrixProperty<Integer> keepAliveTime, TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
return existingConcurrencyStrategy != null
? existingConcurrencyStrategy.getThreadPool(threadPoolKey, corePoolSize,
maximumPoolSize, keepAliveTime, unit, workQueue)
: super.getThreadPool(threadPoolKey, corePoolSize, maximumPoolSize,
keepAliveTime, unit, workQueue);
}
@Override
public <T> Callable<T> wrapCallable(Callable<T> callable) {
return existingConcurrencyStrategy != null
? existingConcurrencyStrategy
.wrapCallable(new ApiContextCallable<T>(callable))
: super.wrapCallable(new ApiContextCallable<T>(callable));
}
}
class ApiContextCallable<V> implements Callable<V> {
private final Callable<V> delegate;
private final Object delegateObject;
private Object originalObject;
public ApiContextCallable(Callable<V> delegate, Object delegateObject) {
Assert.notNull(delegate, "delegate cannot be null");
this.delegate = delegate;
this.delegateObject = delegateObject;
}
public ApiContextCallable(Callable<V> delegate) {
this(delegate, TokenContext.get());
}
public V call() throws Exception {
try {
// 重点在这里 TokenContext 是我自己的上下文
// TokenContext.get() 和 TokenContext.set() 都是对自己的ThreadLocal操作
this.originalObject = TokenContext.get();
TokenContext.set(this.delegateObject);
V reV = this.delegate.call();
return reV;
} finally {
TokenContext.set(this.originalObject);
this.originalObject = null;
}
}
public String toString() {
return this.delegate.toString();
}
}
}
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels