在前面的文章中,我们已经发现了开关的踪影,例如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. mac 连接linux

    1.ssh 通过ssh 的方式直接连接linux ssh name@ip -22 例:ssh  zyc@192.168.1.100 -22 这个的前提是linux 要开启ssh 服务 先看一下linu ...

  2. POJ 1286 Necklaces of Beads (Burnside定理,有限制型)

    题目链接:http://vjudge.net/problem/viewProblem.action?id=11117 就是利用每种等价情形算出置换节之后算组合数 #include <stdio. ...

  3. SGU 196.Matrix Multiplication

    时间限制:0.25s 空间限制:4M Solution n=10000,m=100000,显然不能用矩阵乘法乘出来. S= ATA 对于矩阵S的一行,所有在A矩阵中1位置的元素都相等,并且都等于这一行 ...

  4. centos 7 samba相关命令

    1.安装相关包 yum install samba samba-client samba-common 2.启动smb的命令 systemctl enable smb.service systemct ...

  5. [转]NodeJS、NPM安装配置步骤(windows版本)

    1.windows下的NodeJS安装是比较方便的(v0.6.0版本之后,支持windows native),只需要登陆官网(http://nodejs.org/),便可以看到首页的“INSTALL” ...

  6. js事件处理 —— 详解

    对于JS事件处理分为四部分: 1.html事件处理程序 直接添加到HTML结构中 解析:用html处理程序可以直接在button元素里直接调用,但是维护性不是很方便 <!DOCTYPE html ...

  7. An erroroccurred while filtering resources

    maven报错: maven An error occurred while filtering resources Maven -> Update Project... resolved th ...

  8. 小记搭建WAPM运行ThinkPHP时所需要的配置

    最近因为项目而接触到了Thinkphp,正在上手中.但昨天遇到几个问题,一下子牵连出之前搭建WAPM(windows+apache+PHP+MySQL)遗留的配置问题. aphache\conf目录下 ...

  9. python unicode&str 转化

    从数据库中取出的值是Unicode编码的 需要转化为str才能正常使用 参考: http://www.mamicode.com/info-detail-308445.html

  10. 酷炫地给py代码标上行数

    Python IDLE是没有显示行号的功能的,今天学了一个方式可以酷炫地给自己的代码加上行号,该方法直接修改代码,慎用哦!代码如下: import fileinput for line in file ...