feign之间传递oauth2-token的问题和解决~续

之前写过关于修改hystric的隔离《feign之间传递oauth2-token的问题和解决》方式来在feign调用各个微服务中传递token,修改为SEMAPHORE之后,会有一些性能的问题,可能出现请求积压,请求雪崩等问题,所以今天需要使用另一种方法,就是通过自定义的隔离对象重写wrapCallable方法来实现。

  • CustomFeignHystrixConcurrencyStrategy代码
    import com.netflix.hystrix.strategy.HystrixPlugins;
    import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.context.annotation.Primary;
    import org.springframework.stereotype.Component;
    import org.springframework.web.context.request.RequestAttributes;
    import org.springframework.web.context.request.RequestContextHolder;
     
    import java.util.concurrent.Callable;
     

    @Slf4j
    @Primary
    @Component
    public class CustomFeignHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy {
     
        public CustomFeignHystrixConcurrencyStrategy() {
            try {
     
                HystrixPlugins.getInstance().registerConcurrencyStrategy(this);
     
            } catch (Exception e) {
                log.error("Failed to register Sleuth Hystrix Concurrency Strategy", e);
            }
        }
     
        @Override
        public <T> Callable<T> wrapCallable(Callable<T> callable) {
            RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
            return new WrappedCallable<>(callable, requestAttributes);
        }
     
        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;
            }
     
            /**
             * feign opens the fuse (hystrix): feign.hystrix.enabled=ture, and uses the default signal isolation level,
             * The HttpServletRequest object is independent of each other in the parent thread and the child thread and is not shared.
             * So the HttpServletRequest data of the parent thread used in the child thread is null,
             * naturally it is impossible to obtain the token information of the request header In a multithreaded environment, call before the request, set the context before the call
             *
             * feign启用了hystrix,并且feign.hystrix.enabled=ture。采用了线程隔离策略。
             * HttpServletRequest 请求在对象在父线程和子线程中相互独立,且不共享
             * 所以父线程的 HttpServletRequest 在子线程中为空,
             * 所以通常 在多线程环境中,在请求调用之前设置上下文
             * @return T
             * @throws Exception Exception
             */
            @Override
            public T call() throws Exception {
                try {
                    // Set true to share the parent thread's HttpServletRequest object setting
                    RequestContextHolder.setRequestAttributes(requestAttributes, true);
                    return target.call();
                } finally {
                    RequestContextHolder.resetRequestAttributes();
                }
            }
        }
    }


posted @ 2022-08-24 14:00  张占岭  阅读(301)  评论(0编辑  收藏  举报