zoukankan      html  css  js  c++  java
  • 解决SpringCloud使用Feign跨服调用时header请求头中的信息丢失

    在使用SpringCloud进行Feign跨服调用时header请求头中的信息会丢失,是因为Feign是不会带上当前请求的Cookie信息和头信息的,这个时候就需要重写请求拦截。

    1、需要重写RequestInterceptor接口中的apply方法(前提是Feign的隔离策略为SEMAPHORE)

    @Component
    public class FeignInterceptor implements RequestInterceptor{
    
        @Override
        public void apply(RequestTemplate template) {
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            if (attributes != null) {
                HttpServletRequest request = attributes.getRequest();
               //将token信息放入header中
                template.header("access_token",request.getHeader("access_token"));
            }
        }
    }    

    注意当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 <T> Callable<T> wrapCallable(Callable<T> callable) {
            RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
            return new WrappedCallable<>(callable, requestAttributes);
        }
    
        @Override
        public ThreadPoolExecutor getThreadPool(HystrixThreadPoolKey threadPoolKey,
                                                HystrixProperty<Integer> corePoolSize, HystrixProperty<Integer> maximumPoolSize,
                                                HystrixProperty<Integer> keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
            return this.delegate.getThreadPool(threadPoolKey, corePoolSize, maximumPoolSize, keepAliveTime,
                    unit, workQueue);
        }
    
        @Override
        public BlockingQueue<Runnable> getBlockingQueue(int maxQueueSize) {
            return this.delegate.getBlockingQueue(maxQueueSize);
        }
    
        @Override
        public <T> HystrixRequestVariable<T> getRequestVariable(HystrixRequestVariableLifecycle<T> rv) {
            return this.delegate.getRequestVariable(rv);
        }
    
        static class WrappedCallable<T> implements Callable<T> {
            private final Callable<T> target;
            private final RequestAttributes requestAttributes;
    
            public WrappedCallable(Callable<T> 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();
                }
            }
        }
    }
  • 相关阅读:
    Oracle 手工创建awr快照,获取报告
    Oracle块修改跟踪功能
    Oracle 反向索引(反转建索引) 理解
    oracle聚簇表的理解 (转自:https://blog.csdn.net/gumengkai/article/details/51009345 )
    Fix the iOS code signing issue when using Jenkins
    ios系统crash文件分析
    python版本管理
    python requirements.txt
    android makefile protoc路径添加
    初识tflite源码
  • 原文地址:https://www.cnblogs.com/Amaris-Lin/p/10654514.html
Copyright © 2011-2022 走看看