因为浏览器请求第一个模块携带的token和各类消息头在第一个模块调用第二个模块的时候会重构请求,这个请求是没有消息头,导致第一个请求的消息头到第二个模块会丢失
解决方案:使用请求拦截器 保存第一个请求的 headers
@Component
public class FeignAuthRequestInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate template) {
ServletRequestAttributes servletRequestAttributes= (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
if(servletRequestAttributes!=null){
HttpServletRequest request = servletRequestAttributes.getRequest();
Enumeration headerNames = request.getHeaderNames();
if(headerNames!=null){
while(headerNames.hasMoreElements()){
String name = headerNames.nextElement();
String header= request.getHeader(name);
template.header(name, header);
}
}
}
}
}
注意:当 Feign 的隔离策略默认为 THREAD 时,由于当使用该隔离策略时,是没办法拿到 ThreadLocal 中的值的,但是 RequestContextHolder 源码中,使用了两个 ThreadLocal,因此当使用该隔离策略时是没有办法通过 RequestContextHolder 获取到 request 对象的,这时如果你还坚持使用 THREAD 这个隔离策略就需要自定义策略(重写 THREAD 隔离策略)
/**
* 自定义并发策略
* 将现有的并发策略作为新并发策略的成员变量
* 在新并发策略中,返回现有并发策略的线程池、Queue
*
* hystrix.command.default.execution.isolation.strategy=THREAD Hystrix的默认隔离策略(官方推荐,当使用该隔离策略时,是没办法拿到 ThreadLocal 中的值的,但是
* RequestContextHolder 源码中,使用了两个ThreadLocal)
* hystrix.command.default.execution.isolation.strategy=SEMAPHORE (将隔离策略改为SEMAPHORE 也可以解决这个问题,但是官方并不推荐这个策略,因为这个策略对网络资源消耗比较大)
*
* 主要是解决当 Hystrix的默认隔离策略是THREAD时,不能通过RequestContextHolder获取到request对象的问题
*
* Create By yxl on 2018/5/22
*/
@Component
public class FeignConfig extends HystrixConcurrencyStrategy {
private static final Logger log = LoggerFactory.getLogger(FeignConfig.class);
private HystrixConcurrencyStrategy delegate;
public FeignConfig() {
try {
this.delegate = HystrixPlugins.getInstance().getConcurrencyStrategy();
if (this.delegate instanceof FeignConfig) {
// 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 void logCurrentStateOfHystrixPlugins(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.");
}
}
@Override
public Callable wrapCallable(Callable callable) {
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
return new WrappedCallable<>(callable, requestAttributes);
}
@Override
public ThreadPoolExecutor getThreadPool(HystrixThreadPoolKey threadPoolKey,
HystrixProperty corePoolSize, HystrixProperty maximumPoolSize,
HystrixProperty keepAliveTime, TimeUnit unit, BlockingQueue workQueue) {
return this.delegate.getThreadPool(threadPoolKey, corePoolSize, maximumPoolSize, keepAliveTime,
unit, workQueue);
}
@Override
public BlockingQueue getBlockingQueue(int maxQueueSize) {
return this.delegate.getBlockingQueue(maxQueueSize);
}
@Override
public HystrixRequestVariable getRequestVariable(HystrixRequestVariableLifecycle rv) {
return this.delegate.getRequestVariable(rv);
}
static class WrappedCallable implements Callable {
private final Callable target;
private final RequestAttributes requestAttributes;
public WrappedCallable(Callable target, RequestAttributes requestAttributes) {
this.target = target;
this.requestAttributes = requestAttributes;
}
@Override
public T call() throws Exception {
try {
RequestContextHolder.setRequestAttributes(requestAttributes);
return target.call();
} finally {
RequestContextHolder.resetRequestAttributes();
}
}
}
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)