暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

HystrixConcurrencyStrategy ttl解决hystrix上下文传递问题

原创 soul0202 2025-06-19
219

普通的 ThreadLocal 不能在线程池线程之间传递,而 Hystrix 默认使用线程池隔离策略,因此上下文丢失。TransmittableThreadLocal(简称 TTL)是阿里开源的一个库,可以实现线程池线程之间的 ThreadLocal 传递。

线程上下文(如 ThreadLocal 数据、请求上下文等)在线程切换过程中丢失。这是因为 Hystrix 默认会在线程池中执行命令(隔离策略为 SEMAPHORE 除外),而线程池切换会导致当前线程的 ThreadLocal 上下文信息丢失。

  • Hystrix 默认使用 ThreadPoolTaskExecutor 执行命令。
  • 如果你使用了类似 ThreadLocal 存储的上下文数据(例如用户信息、请求头、traceId 等),在 Hystrix 切换线程后这些数据会丢失。
  • 解决方法是通过继承 HystrixConcurrencyStrategy 并重写其 wrapCallable 方法,将当前线程的上下文复制到新线程中。

    解决方案步骤

    1. 添加 TTL 依赖

    Maven 依赖如下:

    com.alibaba transmittable-thread-local 2.12.4


    2. 自定义 HystrixConcurrencyStrategy

    以下是一个自定义 HystrixConcurrencyStrategy 的示例,用于集成 TTL:

    public class TtlHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy { private HystrixConcurrencyStrategy delegate; public TtlHystrixConcurrencyStrategy() { this.delegate = HystrixPlugins.getInstance().getConcurrencyStrategy(); if (this.delegate instanceof TtlHystrixConcurrencyStrategy) { // 防止重复设置 return; } HystrixCommandExecutionHook executionHook = HystrixPlugins.getInstance().getCommandExecutionHook(); HystrixEventNotifier eventNotifier = HystrixPlugins.getInstance().getEventNotifier(); HystrixMetricsPublisher metricsPublisher = HystrixPlugins.getInstance().getMetricsPublisher(); HystrixPropertiesStrategy propertiesStrategy = HystrixPlugins.getInstance().getPropertiesStrategy(); HystrixPlugins.reset(); HystrixPlugins.getInstance().registerConcurrencyStrategy(this); HystrixPlugins.getInstance().registerCommandExecutionHook(executionHook); HystrixPlugins.getInstance().registerEventNotifier(eventNotifier); HystrixPlugins.getInstance().registerMetricsPublisher(metricsPublisher); HystrixPlugins.getInstance().registerPropertiesStrategy(propertiesStrategy); } @Override public Callable wrapCallable(Callable callable) { // 使用 TTL 的 TtlCallable 包装 return TtlCallable.get(callable); } // 其余方法委托给原来的策略 @Override public ThreadPoolExecutor getThreadPool(...) { return delegate.getThreadPool(...); } @Override public BlockingQueue getBlockingQueue(int maxQueueSize) { return delegate.getBlockingQueue(maxQueueSize); } @Override public HystrixThreadPool getThreadPool(HystrixThreadPoolKey threadPoolKey, HystrixProperty corePoolSize, HystrixProperty maximumPoolSize, HystrixProperty keepAliveTime, TimeUnit unit, BlockingQueue workQueue) { return delegate.getThreadPool(threadPoolKey, corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue); } @Override public RequestVariable getRequestVariable(RequestVariableLifecycle rv) { return delegate.getRequestVariable(rv); } }


    3. 注册自定义策略

    在应用启动时(如 Spring Boot 的 @PostConstruct 或自定义配置类中)注册:

    @PostConstruct public void init() { new TtlHystrixConcurrencyStrategy(); // 触发注册 }


    ✅ 适用场景

    • 在使用 Hystrix + Feign + Ribbon + Sleuth/Trace/MDC 时需要上下文透传;

    • 在子线程中需要访问主线程设置的上下文数据(如用户ID、TraceID);

    • 需要自定义线程隔离时保证上下文不丢失。

    ✅Spring Cloud 解决方案

    如果你使用的是 Spring Cloud Alibaba 中的 Sentinel+Feign,那不再推荐使用 Hystrix,可以直接切换为 Resilience4j + TTL 或 Sentinel,TTL 在这些新方案中支持更完善。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论