• motan源码分析九:开关


    在前面的文章中,我们已经发现了开关的踪影,例如cluster,motan支持多个cluster,当前的cluster因为开关关闭的情况下,就会使用下一个cluster。

    1.开关相关的类和接口主要都在包com.weibo.api.motan.switcher下,类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.开关的服务接口SwitcherService

    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);

    3.监听开关变化的接口SwitcherListener,主要是监听开关值的变化,由相关的监听者自行实现

    4.SwitcherService的实现类LocalSwitcherService

    public class LocalSwitcherService implements SwitcherService {
    
        private static ConcurrentMap<String, Switcher> switchers = new ConcurrentHashMap<String, Switcher>();//开关集合map
    
        private Map<String, List<SwitcherListener>> listenerMap = new ConcurrentHashMap();//监听器map
    
        @Override
        public Switcher getSwitcher(String name) {
            return switchers.get(name);
        }
    
        @Override
        public List<Switcher> getAllSwitchers() {
            return new ArrayList<Switcher>(switchers.values());//获取当前开关服务下的所有开关
        }
    
        private 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) {//为某个开关添加监听器
            synchronized (listenerMap) {
                if (listenerMap.get(switcherName) == null) {
                    List listeners = Collections.synchronizedList(new ArrayList());
                    listenerMap.put(switcherName, listeners);
                    listeners.add(listener);
                } else {
                    List listeners = listenerMap.get(switcherName);
                    if (!listeners.contains(listener)) {
                        listeners.add(listener);
                    }
                }
            }
        }
    
        @Override
        public void unRegisterListener(String switcherName, SwitcherListener listener) {//为某个开关移出监听器
            synchronized (listenerMap) {
                if (listener == null) {
                    listenerMap.remove(switcherName);
                } else {
                    List<SwitcherListener> listeners = listenerMap.get(switcherName);
                    listeners.remove(listener);
                }
            }
        }
    
    }
  • 相关阅读:
    JAVA CookieUtil
    Maven打包时提示No runnable methods的解决方案
    Spring MVC中Junit测试简单讲解
    C# 连接MongoDB,含用户验证
    Spring中同一个service中方法相互调用事务不生效问题解决方案
    004. vue html模板字符串转为ast(js对象)
    03事件模型-发布订阅模式
    000 学习vue源码里面一些处理技巧
    02 响应式原理
    my-ts-axios
  • 原文地址:https://www.cnblogs.com/mantu/p/5887049.html
Copyright © 2020-2023  润新知