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); } } } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?