配置Hystrix的隔离策略、解决RequestContextHolder.getRequestAttributes()空指针异常

Hystrix有隔离策略和RequestContextHolder

Hystrix有隔离策略包括:THREAD和SEMAPHORE

当隔离策略为 THREAD 时,是没办法拿到ThreadLocal中的值的。例如下面这段代码,我要使用Feign调用某个远程的方法,但是获取的(RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes())requestAttributes为Null、现在我的 feign.hystrix.enabled=true

@Configuration
@Controller
public class FeignRequestConfig {

    private static Logger logger = LoggerFactory.getLogger(FeignRequestConfig.class);

    @Bean
    public RequestInterceptor requestInterceptor(){

        RequestInterceptor requestInterceptor = new RequestInterceptor() {

            @Override
            public void apply(RequestTemplate requestTemplate) {
                // 现在获取的requestAttributes为null
                RequestAttributes requestAttributes =             
                                           RequestContextHolder.getRequestAttributes();
                if (requestAttributes == null) {
                    return;
                }

            }

        };

        return requestInterceptor;
    }
}

解决方法(方案一)

requestInterceptor 之所以为null,原因就在于,Hystrix的默认隔离策略是THREAD 。而RequestContextHolder源码中,使用了两个ThreadLocal、调整Hystrix的默认隔离策略:

hystrix.command.default.execution.isolation.strategy=SEMAPHORE

注:该方案不是官方很推荐的方案,官方推荐自定义并发策略,需要自己编写一个类,让其继承
HystrixConcurrencyStrategy类,重写wrapCallable方法,【由于自定义并发策略方案以及后续带来的问题,我还没有落地实践,不敢乱写,尽请谅解、后续实践后,再补充文章】

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在使用Feign集成Hystrix时,由于Hystrix的线程池隔离机制,无法直接获取到`RequestContextHolder.currentRequestAttributes()`,因为在新的线程无法访问当前请求的上下文信息。 解决这个问题的一种常见方法是,通过`HystrixConcurrencyStrategy`来传递上下文信息。下面是一个简单的案例解决方案: 1. 创建一个自定义的`HystrixConcurrencyStrategy`类,继承自`HystrixConcurrencyStrategy`: ```java public class RequestContextHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy { @Override public <T> Callable<T> wrapCallable(Callable<T> callable) { HttpServletRequest request = RequestContextHolder.getRequestAttributes(); // 通过自定义的CallableWrapper将请求上下文信息传递到Hystrix的线程 return new RequestContextCallableWrapper<>(callable, request); } // 在这里重写一些其他需要的方法 } ``` 2. 创建一个自定义的`CallableWrapper`类,用于在包装`Callable`时传递请求上下文信息: ```java public class RequestContextCallableWrapper<T> implements Callable<T> { private final Callable<T> delegate; private final HttpServletRequest request; public RequestContextCallableWrapper(Callable<T> delegate, HttpServletRequest request) { this.delegate = delegate; this.request = request; } @Override public T call() throws Exception { try { RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(request)); return delegate.call(); } finally { RequestContextHolder.resetRequestAttributes(); } } } ``` 3. 在启动类,将自定义的`HystrixConcurrencyStrategy`注册到Hystrix: ```java @Configuration public class HystrixConfig { @PostConstruct public void init() { HystrixPlugins.getInstance().registerConcurrencyStrategy(new RequestContextHystrixConcurrencyStrategy()); } } ``` 这样,就可以在使用Feign集成Hystrix时,通过`RequestContextHolder.currentRequestAttributes()`获取到请求上下文信息了。 需要注意的是,上述代码的`RequestContextHolder`和`ServletRequestAttributes`是Spring Framework的类,如果你使用的是其他框架,请相应地修改代码。同时,该解决方案也适用于其他情况下无法获取到请求上下文信息的场景。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值