hystrix拆解一: HystrixXXXKey Factory设计

736 阅读2分钟

前言

hystrix是netflix开源的一款用于隔离远程服务调用、第三方访问的容错库,又称断路器,为复杂的分布式系统中不可避免的故障提供阻断和动态恢复的能力,避免出现级联故障(俗称雪崩). hystrix目前已经停止官方维护,相关团队已转向开发更具有实时性和自适应能力的组件,例如 resilience4j。即便如此,hystrix能够很好的应对对系统实时状态并非非常敏感的系统场景,内部的实现和设计依然有很多值得自己学习的内容。

概述

hystrix中组织隔离的维度包含了CommandGroup和Command, 为了标识相关业务对象,hystrix使用Key的概念进行区分。例如HystrixCommandGroupKey、HystrixCommandKey、HystrixThreadPoolKey等,这些Key管理hystrix组织业务的主要依据,因此首先理解Key的特性将有利于理解后续的业务逻辑。

Key Factory

HystrixCommandGroupKey: 多个HystrixCommand的分组名标识对象,用于后续基于分组进行告警、报表统计或看板展示等功能;

HystrixCommandKey: 具体HystrixCommand的标识,用于执行熔断、状态统计、监控、请求缓存等功能;

HystrixThreadPoolKey: HystrixThreadPool的标识,如果不指定,默认与HystrixCommandGroupKey保持一致;

模板方式组织Key的操作定义

HystrixKey定义了Key的get的基本操作; HystrixDefaultKey定义了HystrixKey的默认抽象实现; HystrixXXXDefault则通过defaultKey的模板实现具体的业务子类。

以key为索引、以Key信息的Default类为Value, 使用ConcurrentHashMap来存储每种类型的Key对象;
使用map.putIfAbsent方法来避免重复创建Key;

public class InternMap<K, V> {
    private final ConcurrentMap<K, V> storage = new ConcurrentHashMap<K, V>();
    private final ValueConstructor<K, V> valueConstructor;

    public interface ValueConstructor<K, V> {
        V create(K key);
    }

    public InternMap(ValueConstructor<K, V> valueConstructor) {
        this.valueConstructor = valueConstructor;
    }

    public V interned(K key) {
        // 先尝试获取
        V existingKey = storage.get(key);
        V newKey = null;
        if (existingKey == null) {
            // 未存在时调用构造方法生成,通过putIfAbsent写入新值或返回已存在的值
            newKey = valueConstructor.create(key);
            existingKey = storage.putIfAbsent(key, newKey);
        }
        
        // if absent, put return null; 
        // else return old value
        return existingKey != null ? existingKey : newKey;
    }

    public int size() {
        return storage.size();
    }
}

使用内部单例工厂方法封装InternMap的初始化和对HystrixDefaultKey的调用,实现工厂机制。

总结

对于Key的管理使用模板和工厂两种模式的组合,这种组织默认实现和封装内部实现的机制可以借鉴。