事件驱动模式-Tomcat和zookeeper教你如何玩

事件驱动模式的基本原理是构件并不直接调用过程,而是触发一个或多个事件。系统中的其他构件可以注册相关的事件,触发一个事件时,系统会自动调用注册了该事件的构件过程,即触发事件会导致另一构件中过程的调用。 通常的事件驱动设计中,会涉及到事件,事件监听,事件发布接口。流程如下:
事件驱动模式-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监听机制。流程如下:
事件驱动模式-Tomcat和zookeeper教你如何玩
文章图片

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教你如何玩】

    推荐阅读