• Hystrix Plugins插件机制解析


    Hystrix Plugins插件机制

    Hystrix通过SPI提供了插件扩展机制,有如下几种插件:

        HystrixConcurrencyStrategy:并发
        HystrixEventNotifier:通知
        HystrixMetricsPublisher:度量
        HystrixPropertiesStrategy:Properties配置
        HystrixCommandExecutionHook:回调函数
        HystrixDynamicProperties:配置

    以上插件都由HystrixPlugins统一管理,负责加载和实例化。
    SPI插件机制

    本篇文章就不讲解SPI,请见:https://juejin.cn/post/6988416649476964382
    Hystrix插件机制实现

    举例HystrixConcurrencyStrategy来进行讲解
    HystrixConcurrencyStrategy插件讲解

    插件实现的相关类如下

        实现默认的抽象类HystrixConcurrencyStrategy
        官方仅提供了HystrixConcurrencyStrategyDefault的默认实现,继承了1中的抽象类

    HystrixConcurrencyStrategy类的作用解析

        Hystrix只有一个作用,实例化线程执行器。其核心方法为getThreadPool(),其本质就是把参数传进来,然后实例化一个ThreadPoolExecutor
        实际上HystrixConcurrencyStrategyDefault是直接继承HystrixConcurrencyStrategy,并且没有重写getThreadPool()方法,所以直接调用到下面的getThreadPool()逻辑的

    /**
     * 目前只有这个使用,只分析这个就好
     * @param threadPoolKey key
     * @param threadPoolProperties 参数
     * @return 线程池执行器
     */
    public ThreadPoolExecutor getThreadPool(final HystrixThreadPoolKey threadPoolKey, HystrixThreadPoolProperties threadPoolProperties) {
        // 获取ThreadFactory
        final ThreadFactory threadFactory = getThreadFactory(threadPoolKey);

        // 获取请求参数
        final boolean allowMaximumSizeToDivergeFromCoreSize = threadPoolProperties.getAllowMaximumSizeToDivergeFromCoreSize().get();
        final int dynamicCoreSize = threadPoolProperties.coreSize().get();
        final int keepAliveTime = threadPoolProperties.keepAliveTimeMinutes().get();
        final int maxQueueSize = threadPoolProperties.maxQueueSize().get();
        final BlockingQueue<Runnable> workQueue = getBlockingQueue(maxQueueSize);

        // allowMaximumSizeToDivergeFromCoreSize = true,就允许核心线程起作用
        if (allowMaximumSizeToDivergeFromCoreSize) {
            final int dynamicMaximumSize = threadPoolProperties.maximumSize().get();
            // allowMaximumSizeToDivergeFromCoreSize=true情况下,核心线程数必须小于等于最大线程数
            if (dynamicCoreSize > dynamicMaximumSize) {
                logger.error("Hystrix ThreadPool configuration at startup for : " + threadPoolKey.name() + " is trying to set coreSize = " +
                        dynamicCoreSize + " and maximumSize = " + dynamicMaximumSize + ".  Maximum size will be set to " +
                        dynamicCoreSize + ", the coreSize value, since it must be equal to or greater than the coreSize value");
                return new ThreadPoolExecutor(dynamicCoreSize, dynamicCoreSize, keepAliveTime, TimeUnit.MINUTES, workQueue, threadFactory);
            } else {
                return new ThreadPoolExecutor(dynamicCoreSize, dynamicMaximumSize, keepAliveTime, TimeUnit.MINUTES, workQueue, threadFactory);
            }
        } else {
            return new ThreadPoolExecutor(dynamicCoreSize, dynamicCoreSize, keepAliveTime, TimeUnit.MINUTES, workQueue, threadFactory);
        }
    }

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        33

    怎么加载HystrixConcurrencyStrategy插件

    初始化HystrixThreadPool时,默认会调用到HystrixThreadPoolDefault,并进行实例化

    class HystrixThreadPoolDefault implements HystrixThreadPool {
        // ....其他逻辑
        public HystrixThreadPoolDefault(HystrixThreadPoolKey threadPoolKey, HystrixThreadPoolProperties.Setter propertiesDefaults) {
            this.properties = HystrixPropertiesFactory.getThreadPoolProperties(threadPoolKey, propertiesDefaults);
            // !!!实例化HystrixConcurrencyStrategy!!
            HystrixConcurrencyStrategy concurrencyStrategy = HystrixPlugins.getInstance().getConcurrencyStrategy();
            this.queueSize = properties.maxQueueSize().get();
            // 实例化了一个线程池:concurrencyStrategy.getThreadPool(threadPoolKey, properties)
            this.metrics = HystrixThreadPoolMetrics.getInstance(threadPoolKey,
                    concurrencyStrategy.getThreadPool(threadPoolKey, properties),
                    properties);
            // 最后线程池在这里赋值给this.threadPool
            this.threadPool = this.metrics.getThreadPool();
            this.queue = this.threadPool.getQueue();

            /* strategy: HystrixMetricsPublisherThreadPool */
            HystrixMetricsPublisherFactory.createOrRetrievePublisherForThreadPool(threadPoolKey, this.metrics, this.properties);
        }
        // ....其他逻辑
    }

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20

    可见最终调用了HystrixPlugins.getInstance().getConcurrencyStrategy()来及性能获取具体的策略实例

        首先从属性"hystrix.plugin.HystrixConcurrencyStrategy.implementation=xxx“,看看有没自定义的策略类,如果有就用Class.forName加载
        1.1 举个参数例子:hystrix.plugin.HystrixConcurrencyStrategy.implementation=com.lds.hystrix.MyHystrixConcurrencyStrategy
        如果没有返回null,就会用CAS来吧策略实例替换为默认的HystrixConcurrencyStrategyDefault,否则用自定义的

    public class HystrixPlugins {
        // ....其他逻辑
        
        public HystrixConcurrencyStrategy getConcurrencyStrategy() {
            // 获取策略实例
            if (concurrencyStrategy.get() == null) {
                // 走到这部说明不存在
                // check for an implementation from Archaius first
                // 不存在则通过getPluginImplementation获取,这个会从"hystrix.plugin.HystrixConcurrencyStrategy.implementation“属性值里面获取
                //   如果没有设置对应的实例返回,就会返回null
                Object impl = getPluginImplementation(HystrixConcurrencyStrategy.class);
                if (impl == null) {
                    // 返回null,就会默认采用HystrixConcurrencyStrategyDefault来进行实例化对应的线程池
                    // nothing set via Archaius so initialize with default
                    concurrencyStrategy.compareAndSet(null, HystrixConcurrencyStrategyDefault.getInstance());
                    // we don't return from here but call get() again in case of thread-race so the winner will always get returned
                } else {
                    // we received an implementation from Archaius so use it
                    // 否则用自定义的类来实例化线程池
                    concurrencyStrategy.compareAndSet(null, (HystrixConcurrencyStrategy) impl);
                }
            }
            return concurrencyStrategy.get();
        }
        // ....其他逻辑
    }

    原文链接:https://blog.csdn.net/qq_28666081/article/details/119859627
  • 相关阅读:
    P1121 环状最大两段子段和
    (转)背包9讲
    P1115 最大子段和
    P1108 低价购买
    P1103 书本整理
    P1095 守望者的逃离
    P1091 合唱队形
    P1077 摆花
    hadoop记录topk
    楼天城楼教主的acm心路历程(作为励志用)
  • 原文地址:https://www.cnblogs.com/duanxz/p/16545448.html
Copyright © 2020-2023  润新知