在前面的文章中,我们已经发现了开关的踪影,例如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);
}
}
} }

motan源码分析九:开关的更多相关文章

  1. motan源码分析六:客户端与服务器的通信层分析

    本章将分析motan的序列化和底层通信相关部分的代码. 1.在上一章中,有一个getrefers的操作,来获取所有服务器的引用,每个服务器的引用都是由DefaultRpcReferer来创建的 pub ...

  2. ABP源码分析九:后台工作任务

    文主要说明ABP中后台工作者模块(BackgroundWorker)的实现方式,和后台工作模块(BackgroundJob).ABP通过BackgroundWorkerManager来管理Backgr ...

  3. Heritrix源码分析(九) Heritrix的二次抓取以及如何让Heritrix抓取你不想抓取的URL

    本博客属原创文章,欢迎转载!转载请务必注明出处:http://guoyunsky.iteye.com/blog/644396       本博客已迁移到本人独立博客: http://www.yun5u ...

  4. MyBatis框架的使用及源码分析(九) Executor

    从<MyBatis框架的使用及源码分析(八) MapperMethod>文中我们知道执行Mapper的每一个接口方法,最后调用的是MapperMethod.execute方法.而当执行Ma ...

  5. jQuery源码分析(九) 异步队列模块 Deferred 详解

    deferred对象就是jQuery的回调函数解决方案,它解决了如何处理耗时操作的问题,比如一些Ajax操作,动画操作等.(P.s:紧跟上一节:https://www.cnblogs.com/grea ...

  6. Vue.js 源码分析(九) 基础篇 生命周期详解

    先来看看官网的介绍: 主要有八个生命周期,分别是: beforeCreate.created.beforeMount.mounted.beforeupdate.updated   .beforeDes ...

  7. motan源码分析十:流量切换

    motan提供了流量切换的功能,可以实现把一个group的流量切换到另一个group(一个或多个服务都可以).大家可以使用tomcat部署motan的管理工具,并设置几个组,例如可以参考demo代码: ...

  8. motan源码分析十一:部分特性

    本章将描述motan部分的特性并对源码进行分析. 1.requestid的维护,使用了当前时间左移20位,再和一个自增变量组合 public class RequestIdGenerator { ); ...

  9. motan源码分析八:涉及到底层的客户端调用

    之前我们分析了客户端调用服务端的源码,但是没有涉及到通讯层和序列化层,本文将之前讲过的内容做一次串联. 1.上层通过动态代理调用refer的call,每个refer又对应一个nettyclient,下 ...

随机推荐

  1. 解决ubuntu下的文本编辑器gedit的乱码问题

    缺省配置下,用 Ubuntu 的文本编辑器(Gedit)打开GB18030(繁体中文用户请将这里的出现的GB18030替换成BIG5或BIG5-HKSCS)类型的中文编码文本文件时,将会出现乱码. 出 ...

  2. Linux 添加epel源

    1.epel-release yum install epel-release 这样有些没办法通过yum 安装  可以这样安装(例如redis)

  3. servlet的提交

    servlet的提交和动态改变有点依赖xml 我们点击控件的时候改变了里面的变量,改变了xml,servlet发现变量变了,就会刷新页面 如果xml文档没有更新,浏览器采用缓存而不则行 <for ...

  4. 【HDU4348】【主席树】To the moon

    Problem Description BackgroundTo The Moon is a independent game released in November 2011, it is a r ...

  5. underscorejs-size学习

    2.24 size 2.24.1 语法: _.size(list) 2.24.2 说明: 返回列表的长度. 示例一:返回数组.对象.字符串的长度 //取数组的长度 var length length ...

  6. javascript删除目标div tr 等

    var delTr = document.getElementById("要删除的位置"); // 获取要删除的位置”对象“ delTr.parentNode.removeChil ...

  7. JQuery zoom插件学习

    jquery zoom是一款图片放大插件,经常用在商城商品页面里. 使用JQuery zoom插件,除了需要引入JQuery.js外,还要引入JQuery.zoom.js文件及jqzoom.css文件 ...

  8. Tomcat虚拟主机配置

    3.1.配置虚拟主机 配置虚似主机就是配置一个网站. 在Tomcat服务器配置一个虚拟主机(网站),需要修改conf文件夹下的server.xml这个配置文件,使用Host元素进行配置,打开serve ...

  9. cloudera-scm-server ip改了怎么办了

    1.vi /etc/cloudera-scm-agent/config.ini #改下ip 2.manager 老只看到一个主机 rm -f /var/lib/cloudera-scm-agent/u ...

  10. CodeChef FNCS

    题面:https://www.codechef.com/problems/FNCS 题解: 我们考虑对 n 个函数进行分块,设块的大小为S. 每个块内我们维护当前其所有函数值的和,以及数组中每个元素对 ...