Feign拦截器中获取为空问题排查
public class RequestHeaderHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy {
private final HystrixConcurrencyStrategy existingConcurrencyStrategy;
public RequestHeaderHystrixConcurrencyStrategy(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 ThreadPoolExecutor getThreadPool(HystrixThreadPoolKey threadPoolKey, HystrixThreadPoolProperties threadPoolProperties) {
return existingConcurrencyStrategy != null ?
existingConcurrencyStrategy.getThreadPool(threadPoolKey, threadPoolProperties) :
super.getThreadPool(threadPoolKey, threadPoolProperties);
}
@Override
public <T> Callable<T> wrapCallable(Callable<T> callable) {
Map<String, String> headers = AuthenticationContextHolder.getRequestHeaders();
SysUser userInfo = AuthenticationContextHolder.getUserInfo();
return existingConcurrencyStrategy != null ?
existingConcurrencyStrategy.wrapCallable(new WrappedCallable<T>(callable, headers, userInfo)) :
super.wrapCallable(new WrappedCallable<T>(callable, headers, userInfo));
}
static class WrappedCallable<T> implements Callable<T> {
private final Callable<T> callable;
private final Map<String, String> headers;
private final SysUser userInfo;
public WrappedCallable(Callable<T> callable, Map<String, String> headers, SysUser userInfo) {
this.callable = callable;
this.headers = headers;
this.userInfo = userInfo;
}
@Override
public T call() throws Exception {
try {
AuthenticationContextHolder.setRequestHeaders(headers);
AuthenticationContextHolder.setUserInfo(userInfo);
return callable.call();
} finally {
AuthenticationContextHolder.remove();
}
}
}
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(name = "", havingValue = "true")
@Slf4j
public class HystrixConcurrencyStrategyAutoConfiguration {
@Autowired(required = false)
private HystrixConcurrencyStrategy existingConcurrencyStrategy;
@PostConstruct
public void init() {
HystrixEventNotifier eventNotifier = HystrixPlugins.getInstance().getEventNotifier();
HystrixMetricsPublisher metricsPublisher = HystrixPlugins.getInstance().getMetricsPublisher();
HystrixPropertiesStrategy propertiesStrategy = HystrixPlugins.getInstance().getPropertiesStrategy();
HystrixCommandExecutionHook commandExecutionHook = HystrixPlugins.getInstance().getCommandExecutionHook();
HystrixConcurrencyStrategy concurrencyStrategy = detectRegisteredConcurrencyStrategy();
HystrixPlugins.reset();
// 注册Hystrix并发策略以外的插件
HystrixPlugins.getInstance().registerConcurrencyStrategy(new RequestHeaderHystrixConcurrencyStrategy(concurrencyStrategy));
HystrixPlugins.getInstance().registerEventNotifier(eventNotifier);
HystrixPlugins.getInstance().registerMetricsPublisher(metricsPublisher);
HystrixPlugins.getInstance().registerPropertiesStrategy(propertiesStrategy);
HystrixPlugins.getInstance().registerCommandExecutionHook(commandExecutionHook);
}
private HystrixConcurrencyStrategy detectRegisteredConcurrencyStrategy() {
HystrixConcurrencyStrategy registeredStrategy = HystrixPlugins.getInstance().getConcurrencyStrategy();
if (existingConcurrencyStrategy == null) {
return registeredStrategy;
}
if (registeredStrategy instanceof HystrixConcurrencyStrategyDefault) {
return existingConcurrencyStrategy;
}
if (!existingConcurrencyStrategy.equals(registeredStrategy)) {
log.warn("找到多个 HystrixConcurrencyStrategy, 使用已存在的HystrixConcurrencyStrategy");
}
return existingConcurrencyStrategy;
}
}
@Component
public class FeignRequestInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate requestTemplate) {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (attributes != null) {
HttpServletRequest request = attributes.getRequest();
Enumeration<String> headerNames = request.getHeaderNames();
if (headerNames != null) {
while (headerNames.hasMoreElements()) {
String name = headerNames.nextElement();
String values = request.getHeader(name);
requestTemplate.header(name, values);
}
}
} else {
// RequestContextHolder中获取不到request时,可能是当前线程在Hystrix线程池中,则需要从AuthenticationontextHolder中获取header信息
Map<String, String> headers = AuthenticationContextHolder.getRequestHeaders();
if (MapUtils.isNotEmpty(headers)) {
headers.forEach(requestTemplate::header);
}
}
}
}