springCloud Feign服务之间远程调用丢失消息头原因

springCloud Feign服务之间远程调用丢失消息头原因,第1张

原因:

因为浏览器请求第一个模块携带的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();
            }
        }
    }
}

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/917575.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-16
下一篇 2022-05-16

发表评论

登录后才能评论

评论列表(0条)

保存