事件驱动模式-Tomcat和zookeeper教你如何玩
事件驱动模式的基本原理是构件并不直接调用过程,而是触发一个或多个事件。系统中的其他构件可以注册相关的事件,触发一个事件时,系统会自动调用注册了该事件的构件过程,即触发事件会导致另一构件中过程的调用。 通常的事件驱动设计中,会涉及到事件,事件监听,事件发布接口。流程如下:
文章图片
在tomcat容器的加载,zoomkeeper中watcher机制的实现,都是基于事件驱动实现的。另外,在常见的业务中,用户注册成功后,发送优惠券,发送短信通知的操作。用户支付成功,app消息通知,用户短信通知的操作。都会在完成某项动作,就触发一系列操作。
tomcat7中,事件驱动的实现 在tomcat中,catalina容器包含很多的组件,例如,日志记录器,session管理器,servlet类载入器等等。这些组件都是随着catalina的启动,停止而启动或停止的。catalina容器使用Lifecycle定义容器的生命周期,例如start,容器的启动,stop,容器的停止,destroy,容器的销毁等阶段。源码如下:
public interface Lifecycle {/**
* 初始化阶段
*/
public void init() throws LifecycleException;
/**
* 启动阶段
*/
public void start() throws LifecycleException;
/**
* 停止阶段
*/
public void stop() throws LifecycleException;
/**
* 销毁阶段
*/
public void destroy() throws LifecycleException;
}
LifecycleEvent定义各类事件,代表生命周期的各类阶段,事件的类型包括,before_init,after_init,start,before_start,等等。事件的源码如下:
/**
* 生命周期事件
**/
public final class LifecycleEvent extends EventObject {private static final long serialVersionUID = 1L;
public LifecycleEvent(Lifecycle lifecycle, String type, Object data) {super(lifecycle);
this.type = type;
this.data = https://www.it610.com/article/data;
}/**
* The event data associated with this event.
*/
private Object data = null;
/**
* The event type this instance represents.
*/
private String type = null;
}
LifecycleListener定义事件监听器,监听LifecycleEvent事件,定义监听事件的具体操作。例如,容器关闭时,Session管理必须将Session对象保存到辅助存储器中。事件监听源码如下:
/**
* 事件监听器
*
**/
public interface LifecycleListener {/**
* Acknowledge the occurrence of the specified event.
*
* @param event LifecycleEvent that has occurred
*/
public void lifecycleEvent(LifecycleEvent event);
}
LifecycleSupport事件广播接口,用于发布事件,在触发事件的地方调用发起对应事件的调用。事件发布的源码如下:
/**
* 事件广播
**/
public final class LifecycleSupport {....../**
* 生命周期监听器数组
*/
private LifecycleListener listeners[] = new LifecycleListener[0];
/**
* 添加生命周期事件监听器
*/
public void addLifecycleListener(LifecycleListener listener) {}/**
* 发布事件
*/
public void fireLifecycleEvent(String type, Object data) {LifecycleEvent event = new LifecycleEvent(lifecycle, type, data);
LifecycleListener interested[] = listeners;
for (int i = 0;
i < interested.length;
i++)
interested[i].lifecycleEvent(event);
}/**
* 移除生命周期事件监听器
*/
public void removeLifecycleListener(LifecycleListener listener) {}}
zoomkeeper中watcher机制的实现 在zoomkeeper中使用watcher机制,实现zk客户端感知zk服务器对数据节点创建,修改,删除操作。该机制是基于事件驱动实现的。以zk服务器数据节点修改触发zk客户端操作的为例。zk客户端向zk服务器端注册watcher,在zk服务器修改该数据节点时,会基于TCP连接通知zk对应客户端,触发zk客户端注册的watcher,实现zk的watcher监听机制。流程如下:
文章图片
WatchedEvent,定义了watcher事件。例如,None (-1),没有事件;NodeCreated (1),节点创建;NodeDeleted (2), 节点删除;NodeDataChanged (3), 节点数据修改;NodeChildrenChanged (4),节点子节点修改。源码如下:
public class WatchedEvent {
/**
* 通知状态
*/
final private KeeperState keeperState;
/**
* 事件类型
*/
final private EventType eventType;
/**
* 事件触发的节点路径
*/
private String path;
}
Watcher,事件监听的器,定义了监听各类事件的具体操作。例如,节点数据修改,zk客户端需要的具体操作。源码如下:
public interface Watcher {/**
* 监听watcher事件,执行具体逻辑操作
*/
abstract public void process(WatchedEvent event);
}
zk服务器定义WatchManager,实现事件的发布,大致流程是,定义封装可以序列化的WatchedEvent事件,通过与zk客户端建立的tcp连接发送请求。源码如下:
// zk服务器端的watcher事件发布器
public class WatchManager {/**
*向指定数据节点,发布指定类型的事件
*/
public Set triggerWatch(String path, EventType type) {
return triggerWatch(path, type, null);
}public Set triggerWatch(String path, EventType type, Set supress) {
WatchedEvent e = new WatchedEvent(type,
KeeperState.SyncConnected, path);
HashSet watchers;
synchronized (this) {
watchers = watchTable.remove(path);
if (watchers == null || watchers.isEmpty()) {
if (LOG.isTraceEnabled()) {
ZooTrace.logTraceMessage(LOG,
ZooTrace.EVENT_DELIVERY_TRACE_MASK,
"No watchers for " + path);
}
return null;
}
for (Watcher w : watchers) {
HashSet paths = watch2Paths.get(w);
if (paths != null) {
paths.remove(path);
}
}
}
for (Watcher w : watchers) {
if (supress != null && supress.contains(w)) {
continue;
}
w.process(e);
}
return watchers;
}
}
用户注册成功涉及业务的事件驱动设计 在用户注册成功后,通知会执行发送优惠券的操作,或者发送注册成功的短信,发送用户身份认证的通知等等操作。
ApplicationEvent应用事件。
ApplicationListener应用事件监听器。
ApplicationEventBroadcast事件广播。
GiftCouponListener发送优惠券事件监听,作为用户注册成功后,发送优惠券的逻辑。
UserRegistrationBroadcast定义了用户注册广播实现类,在用户注册成功的位置发布ApplicationEvent事件。
发送优惠券事件监听器GiftCouponListener的代码如下:
/**
* 赠送优惠券的监听
**/
public class GiftCouponListener implements ApplicationListener {@Override
public void onEvent(ApplicationEvent applicationEvent) {Object param = applicationEvent.getParam();
// TODO
// 定义具体的实现逻辑
}@Override
public int getOrder() {
return 0;
}
}
用户注册广播实现类UserRegistrationBroadcast代码如下:
/**
* 用户注册广播
**/
public class UserRegistrationBroadcast implements ApplicationEventBroadcast {private final List listeners;
public UserRegistrationBroadcast(List listeners) {
this.listeners = listeners;
AnnotationAwareOrderComparator.sort(listeners);
}@Override
public void publishEvent(ApplicationEvent event) {
listeners.forEach(applicationListener -> applicationListener.onEvent(event));
}
}
【事件驱动模式-Tomcat和zookeeper教你如何玩】
推荐阅读
- 事件代理
- 事件处理程序
- 两感一练
- Android事件传递源码分析
- 66万奔驰漏油事件看宝宝无理取闹
- 「我的2017」——2017|「我的2017」——2017,大事件盘点
- Quartz|Quartz 源码解析(四) —— QuartzScheduler和Listener事件监听
- --木木--|--木木-- 第二课作业#翼丰会(每日一淘6+1实战裂变被动引流# 6+1模式)
- 设计模式-代理模式-Proxy
- 心理工作要不断的评估现实事件对来访者心理造成的影响是什么