Hystrix 线程池策略时使用ThreadLocal

背景

分页查询单据时,由于单据表数据量很大,单月达到了千万级别,所以,查询先走ES,当ES不可用时,降级走mysql,降级使用了 Hystrix,并且是线程池策略,在实际测试过程中,发现前端提供相同查询参数时,后端会返回不同的响应结果,十分怪异,经排查,组装查询条件时,从上下文里获取了参数,而这些参数是放在 ThreadLocal 里的,ThreadLocal 在不同线程之间的数据隔离是通过每个线程都有一个独立的 ThreadLocal 存储来实现的。然而,Hystrix 使用线程池来实现隔离和限流,这意味着请求可能会在线程池中的不同线程之间切换。这可能导致 ThreadLocal 的数据被意外共享或者丢失。

解决方案

自定义一个 HystrixConcurrencyStrategy,在每次任务执行时正确传递 ThreadLocal 数据。

HystrixConcurrencyStrategy 是 Hystrix 提供的一个扩展点,用于自定义并发执行的行为。通过自定义该策略,可以在 Hystrix 的执行上下文中正确管理 ThreadLocal

java 复制代码
public class MyConcurrencyStrategy extends HystrixConcurrencyStrategy {
    private HystrixConcurrencyStrategy existingConcurrencyStrategy;

    public MyConcurrencyStrategy(HystrixConcurrencyStrategy existingConcurrencyStrategy) {
        this.existingConcurrencyStrategy = existingConcurrencyStrategy == null 
            ? HystrixConcurrencyStrategyDefault.getInstance() : existingConcurrencyStrategy;
    }

    @Override
    public <T> Callable<T> wrapCallable(Callable<T> callable) {
        return new WrappedCallable<>(callable);
    }

    private static class WrappedCallable<T> implements Callable<T> {
        private final Callable<T> actual;
        private final Map<ThreadLocal<?>, Object> threadLocals;

        public WrappedCallable(Callable<T> actual) {
            this.actual = actual;
            this.threadLocals = captureThreadLocals();
        }

        @Override
        public T call() throws Exception {
            Map<ThreadLocal<?>, Object> originalThreadLocals = captureThreadLocals();
            restoreThreadLocals(threadLocals);
            try {
                return actual.call();
            } finally {
                restoreThreadLocals(originalThreadLocals);
            }
        }

        private Map<ThreadLocal<?>, Object> captureThreadLocals() {
            Map<ThreadLocal<?>, Object> threadLocals = new HashMap<>();
            // Capture current ThreadLocal values
            return threadLocals;
        }

        private void restoreThreadLocals(Map<ThreadLocal<?>, Object> threadLocals) {
            // Restore ThreadLocal values
        }
    }
}
相关推荐
WeiLai111222 天前
面试基础--高并发高可用架构深度实践:降级熔断(Hystrix vs Sentinel)核心原理与源码解析
java·分布式·后端·hystrix·面试·架构·sentinel
黄名富1 个月前
Spring Cloud — Hystrix 服务隔离、请求缓存及合并
java·分布式·spring·spring cloud·hystrix·微服务
黄名富2 个月前
Spring Cloud — 微服务容错保护 Hystrix入门
java·spring·spring cloud·hystrix·微服务
小小工匠2 个月前
响应式编程_03响应式编程在Netflix Hystrix 、Spring Cloud Gateway、Spring WebFlux中的应用
hystrix·gateway·响应式编程·webflux
2501_903238652 个月前
Java 9模块开发:IntelliJ IDEA实战指南
java·开发语言·hystrix·个人开发
编程、小哥哥3 个月前
Prometheus + Grafana 监控,验证 Hystrix 超时熔断
hystrix·grafana·prometheus
wei_shuo5 个月前
Spring Cloud OpenFeign:基于Ribbon和Hystrix的声明式服务调用
spring cloud·hystrix·ribbon
漫无目的行走的月亮5 个月前
微服务容错处理Hystrix
spring cloud·hystrix·微服务
编程、小哥哥6 个月前
springcloud之应用服务快速失败熔断降级保护 Hystrix
spring·spring cloud·hystrix
天下蒂一厨6 个月前
hystrix微服务部署
hystrix·微服务·架构