RPC框架Motan 2. Switcher模块介绍

106 阅读3分钟

一、前言

switcher位于motan-core包下,实现业务的开关标识逻辑。

二、类介绍

2. 1 Switcher类

表示开关的基本信息

public class Switcher {
    private boolean on = true; // 状态
    private String name; // 开关名
​
    public Switcher(String name, boolean on) {
        this.name = name;
        this.on = on;
    }
​
    public String getName() {
        return name;
    }
​
    /**
     * isOn: true,服务可用; isOn: false, 服务不可用
     * 
     * @return
     */
    public boolean isOn() {
        return on;
    }
​
    /**
     * turn on switcher
     */
    public void onSwitcher() {
        this.on = true;
    }
​
    /**
     * turn off switcher
     */
    public void offSwitcher() {
        this.on = false;
    }
}

2.2 SwitcherService接口

改接口定义开关的操作逻辑

@Spi(scope = Scope.SINGLETON) // SPI标识,可扩展
public interface SwitcherService {
    /**
     * 获取接口降级开关
     * 
     * @param name
     * @return
     */
    Switcher getSwitcher(String name);
​
    /**
     * 获取所有接口降级开关
     * 
     * @return
     */
    List<Switcher> getAllSwitchers();
​
    /**
     * 初始化开关。
     *
     * @param switcherName
     * @param initialValue
     */
    void initSwitcher(String switcherName, boolean initialValue);
​
    /**
     * 检查开关是否开启。
     * 
     * @param switcherName
     * @return true :设置来开关,并且开关值为true false:未设置开关或开关为false
     */
    boolean isOpen(String switcherName);
​
    /**
     * 检查开关是否开启,如果开关不存在则将开关置默认值,并返回。
     * 
     * @param switcherName
     * @param defaultValue
     * @return 开关存在时返回开关值,开关不存在时设置开关为默认值,并返回默认值。
     */
    boolean isOpen(String switcherName, boolean defaultValue);
​
    /**
     * 设置开关状态。
     * 
     * @param switcherName
     * @param value
     */
    void setValue(String switcherName, boolean value);
​
    /**
     * register a listener for switcher value change, register a listener twice will only fire once
     * 注册开关的监听器,只会触发一次
     * @param switcherName
     * @param listener
     */
    void registerListener(String switcherName, SwitcherListener listener);
​
    /**
     * unregister a listener
     * 取消开关监听器,null取消所有监听器
     * @param switcherName
     * @param listener the listener to be unregistered, null for all listeners for this switcherName
     */
    void unRegisterListener(String switcherName, SwitcherListener listener);
​
}

2.3 SwitcherListener接口

创建监听器的接口

public interface SwitcherListener {
​
    void onValueChanged(String key,Boolean value);// key=开关名字,value=开关状态
}

2.4 LocalSwitcherService类

SwitcherService接口提供的实现类

@SpiMeta(name = "localSwitcherService") // 支持ExtensionLoader
public class LocalSwitcherService implements SwitcherService {
​
    // 全局开关名和开关映射关系
    private static ConcurrentMap<String, Switcher> switchers = new ConcurrentHashMap<String, Switcher>();
​
    // 开关名对应的监听器列表映射关系
    private ConcurrentHashMap<String, List<SwitcherListener>> listenerMap = new ConcurrentHashMap<>();
​
    public static Switcher getSwitcherStatic(String name) {
        return switchers.get(name);
    }
​
    @Override
    public Switcher getSwitcher(String name) {
        return switchers.get(name);
    }
​
    @Override
    public List<Switcher> getAllSwitchers() {
        return new ArrayList<Switcher>(switchers.values());
    }
​
    public static void putSwitcher(Switcher switcher) {
        if (switcher == null) {
            throw new MotanFrameworkException("LocalSwitcherService addSwitcher Error: switcher is null");
        }
​
        switchers.put(switcher.getName(), switcher);
    }
​
    @Override
    public void initSwitcher(String switcherName, boolean initialValue) {
        setValue(switcherName, initialValue);
    }
​
    @Override
    public boolean isOpen(String switcherName) {
        Switcher switcher = switchers.get(switcherName);
        return switcher != null && switcher.isOn();
    }
​
    @Override
    public boolean isOpen(String switcherName, boolean defaultValue) {
        Switcher switcher = switchers.get(switcherName);
        if (switcher == null) {
            switchers.putIfAbsent(switcherName, new Switcher(switcherName, defaultValue));
            switcher = switchers.get(switcherName);
        }
        return switcher.isOn();
    }
​
    @Override
    public void setValue(String switcherName, boolean value) {
        putSwitcher(new Switcher(switcherName, value));
        
        // 触发监听器
        List<SwitcherListener> listeners = listenerMap.get(switcherName);
        if(listeners != null) {
            for (SwitcherListener listener : listeners) {
                listener.onValueChanged(switcherName, value);
            }
        }
    }
​
    @Override
    public void registerListener(String switcherName, SwitcherListener listener) {
        List listeners = Collections.synchronizedList(new ArrayList());
        List preListeners= listenerMap.putIfAbsent(switcherName, listeners);
        if (preListeners == null) {
            listeners.add(listener);
        } else {
            preListeners.add(listener);
        }
    }
​
    @Override
    public void unRegisterListener(String switcherName, SwitcherListener listener) {
            List<SwitcherListener> listeners = listenerMap.get(switcherName);
            if (listener == null) {
                // keep empty listeners
                listeners.clear();
            } else {
                listeners.remove(listener);
            }
    }
}

2.5 MotanSwitcherUtil类

静态开关工具类。一般全局开关使用此类。 使用LocalSwitcherService类的实例对象。

public class MotanSwitcherUtil {
    private static SwitcherService switcherService = new LocalSwitcherService();
​
    public static void initSwitcher(String switcherName, boolean initialValue) {
        switcherService.initSwitcher(switcherName, initialValue);
    }
​
    /**
     * 检查开关是否开启。
     * 
     * @param switcherName
     * @return true :设置了开关,并且开关值为true false:未设置开关或开关为false
     */
    public static boolean isOpen(String switcherName) {
        return switcherService.isOpen(switcherName);
    }
​
    /**
     * 检查开关是否开启,如果开关不存在则将开关置默认值,并返回。
     * 
     * @param switcherName
     * @param defaultValue
     * @return 开关存在时返回开关值,开关不存在时设置开关为默认值,并返回默认值。
     */
    public static boolean switcherIsOpenWithDefault(String switcherName, boolean defaultValue) {
        return switcherService.isOpen(switcherName, defaultValue);
    }
​
    /**
     * 设置开关状态。
     * 
     * @param switcherName
     * @param value
     * @return
     */
    public static void setSwitcherValue(String switcherName, boolean value) {
        switcherService.setValue(switcherName, value);
    }
​
    public static SwitcherService getSwitcherService() {
        return switcherService;
    }
​
    public static void setSwitcherService(SwitcherService switcherService) {
        MotanSwitcherUtil.switcherService = switcherService;
    }
​
    public static void registerSwitcherListener(String switcherName, SwitcherListener listener) {
        switcherService.registerListener(switcherName, listener);
    }
​
}

三、示例

示例代码

        String protocolSwitcher = MotanConstants.PROTOCOL_SWITCHER_PREFIX + "motan";
​
        LocalSwitcherService localSwitcherService = new LocalSwitcherService();// 创建开关操作类
        localSwitcherService.setValue(protocolSwitcher, false);// 开关设置关闭
​
        Switcher switcher = localSwitcherService.getSwitcher(protocolSwitcher);
​
        Assert.assertNotNull(switcher);
        Assert.assertFalse(switcher.isOn());// 开关关闭
​
        localSwitcherService.setValue(protocolSwitcher, true); // 设置开关开启
​
        switcher = localSwitcherService.getSwitcher(protocolSwitcher);