事件驱动模式的基本原理是构件并不直接调用过程,而是触发一个或多个事件。系统中的其他构件可以注册相关的事件,触发一个事件时,系统会自动调用注册了该事件的构件过程,即触发事件会导致另一构件中过程的调用。 通常的事件驱动设计中,会涉及到事件,事件监听,事件发布接口。流程如下:
在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 = 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<Watcher> triggerWatch(String path, EventType type) {
return triggerWatch(path, type, null);
}
public Set<Watcher> triggerWatch(String path, EventType type, Set<Watcher> supress) {
WatchedEvent e = new WatchedEvent(type,
KeeperState.SyncConnected, path);
HashSet<Watcher> 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<String> 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<ApplicationListener> listeners;
public UserRegistrationBroadcast(List<ApplicationListener> listeners) {
this.listeners = listeners;
AnnotationAwareOrderComparator.sort(listeners);
}
@Override
public void publishEvent(ApplicationEvent event) {
listeners.forEach(applicationListener -> applicationListener.onEvent(event));
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/13648.html