自定义HystrixConcurrencyStrategy

背景:项目中采用了Feigin + Hystrix 实现RPC 熔断处理,当使用到了 Hystrix 线程隔离机制时,由于业务中对于 Feigin 调用请求拦截器中统一添加 Token 到请求 Header中,由于多线程的缘故导致拦截器无法正常获取到ThreadLocal中设置的参数。

Tips: 解决ThreadLocal传值和线程池可见性方案有很多种,今天重点介绍下 Hystrix 提供的解决方案。

一、自定义实现HystrixConcurrencyStrategy 和 自定义CallableWrapper 包装器

package com.github.ext;
import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.Callable;

/**
 * 熔断器并发处理策略
 */
public class HystrixConcurrencyStrategyExtension extends HystrixConcurrencyStrategy {
    protected final static ThreadLocal<Map<String, Object>> threadLocal = new ThreadLocal<Map<String, Object>>() {
        @Override
        protected Map<String, Object> initialValue() {
            return new HashMap<>();
        }
    };


    /**
     * 设置属性信息到上下文
     *
     * @param name  属性名称(不能为空)
     * @param value 属性值(不能为空)
     */
    public static void setAttribute(String name, Object value) {
        Objects.requireNonNull(name, "`name` cannot be null");
        Objects.requireNonNull(value, "`value` cannot be null");
        threadLocal.get().putIfAbsent(name, value);
    }

    /**
     * 获取属性值
     *
     * @param name 属性名称
     * @return
     */
    public static <T> Optional<T> getAttribute(String name) {
        Object value = threadLocal.get().get(name);
        return (Optional<T>) Optional.ofNullable(value);
    }

    /**
     * 清除上下文信息
     */
    public static void remove() {
        threadLocal.remove();
    }

    /**
     * 包装Callable处理器
     *
     * @return
     */
    @Override
    public <T> Callable<T> wrapCallable(Callable<T> callable) {
        return new CallableWrapper(callable);
    }

    /**
     * 实现自定义Callable包装器
     * @param <T>
     */
    public static class CallableWrapper<T> implements Callable<T> {

        private final Callable<T> delegate;
        private final Map<String, Object> attributes;

        public CallableWrapper(Callable<T> callable) {
            this.delegate = callable;
            this.attributes = HystrixConcurrencyStrategyExtension.threadLocal.get();
        }

        @Override
        public T call() throws Exception {
            try {
                HystrixConcurrencyStrategyExtension.threadLocal.set(attributes);
                return delegate.call();
            } finally {
                HystrixConcurrencyStrategyExtension.remove();
            }
        }
    }
}

二、将HystrixConcurrencyStrategyExtension注册到 Hystrix 即可。

方式一:通过 Java SPI 扩展机制实现自动注册

在工程 resources/目录下创建目录:META-INF/services/
创建文件:com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy 并将自定义的扩展类名称写入到文件即可,
com.github.ext.HystrixConcurrencyStrategyExtension

方式二:通过Hystrix 提供的编程式 API 来实现注册

HystrixPlugins.reset();
HystrixPlugins.getInstance().registerConcurrencyStrategy(new HystrixConcurrencyStrategyExtension());

测试用例:

//获取当前 Hystrix 并发访问策略
HystrixPlugins.getInstance().getConcurrencyStrategy();
//设置传递参数
HystrixConcurrencyStrategyExtension.setAttribute("token", "HelloWorld!!!");
assert HystrixConcurrencyStrategyExtension.getAttribute("token").equals("HelloWorld!!!");

官方文档:https://github.com/Netflix/Hystrix/wiki/Plugins

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值