背景
项目中使用了zookeeper进行的类似工作流引擎的工作流转,将一次工作请求拆分了4个节点(S/E/T/L)。S阶段做完后,通过zk的watcher触发下一个E节点进行处理,S和E可能为不同的jvm上,所以需要走一个分布式的消息进行通知。
思路
基于zookeeper做持久化watcher,项目中直接使用zookeeper官方api,大致的工作模型:
private synchronized void initNodes(List<String> nodes) {
// 根据zk节点,判断是否需要处理
}
private void syncNodes() {
try {
List<String> nodes = zookeeper.getChildren(ArbitrateConstants.NODE_NID_ROOT, new AsyncWatcher() {
public void asyncProcess(WatchedEvent event) {
syncNodes();// 继续关注node节点变化
}
});
initNodes(nodes);
} catch (KeeperException e) {
syncNodes();
} catch (InterruptedException e) {
// ignore
}
}
- 有两个方法initNodes 和 syncNodes, syncNodes主要是监听zookeeper的节点变化
- syncNodes会通过级联方式,在每次watcher被触发后,就会再挂一次watcher。完成了一个类似链式触发的功能
遇到的问题
系统上线运行后,跑了几天时间,跑出了一个OutOfMemory的问题,jmap dump了下对应的内存数据文件,发现了一个zk使用上的问题.
a. 通过mat分析查看了下jvm中占用内存最大的对象,居然是zookeeper中的一个waitingEvents.:
b. waitingEvents中的WatcherSetEventPair对象中,包含了一个待响应的watchers和对应的响应event事件对象,对应的watchers数量居然有300W个
问题分析:
分析了下WatcherSetEventPair中的处理机制。
Event响应中对应EventType的枚举类型:(存在一个特殊的None类型)
- None (-1),
- NodeCreated (1),
- NodeDeleted (2),
- NodeDataChanged (3),
- NodeChildrenChanged (4);
查了下代码,None类型会在Session expired / connection loss/ auth failed得到对应的触发,对应的触发path为null
代码:
eventThread.queueEvent(new WatchedEvent(
Watcher.Event.EventType.None,
Watcher.Event.KeeperState.Expired, null));
针对None类型,在获取对应的watcher响应时:
public Set<Watcher> materialize(Watcher.Event.KeeperState state,
Watcher.Event.EventType type,
String clientPath)
{
Set<Watcher> result = new HashSet<Watcher>();
switch (type) {
case None:
result.add(defaultWatcher);
for(Set<Watcher> ws: dataWatches.values()) {
result.addAll(ws);
}
for(Set<Watcher> ws: existWatches.values()) {
result.addAll(ws);
}
for(Set<Watcher> ws: childWatches.values()) {
result.addAll(ws);
}
// clear the watches if auto watch reset is not enabled
if (ClientCnxn.getDisableAutoResetWatch() &&
state != Watcher.Event.KeeperState.SyncConnected)
{
synchronized(dataWatches) {
dataWatches.clear();
}
synchronized(existWatches) {
existWatches.clear();
}
synchronized(childWatches) {
childWatches.clear();
}
}
return result;
针对出现None的类型,会将所有的watcher进行触发,同时并不会移除watcher,所以,watcher会在下一次reconnect成功后再次触发,除非设置DisableAutoResetWatch
总结
a. 需要明确watcher的触发条件和触发case场景。特别注意,None类型可能会引起触发2次watcher调用
(截取了淘宝同学的blog : http://rdc.taobao.com/team/jm/archives/1047)
event For “/path”
defaultWatcher
exists
(“/path”)
getData
(“/path”)
getChildren
(“/path”)
EventType.None |
√ |
√ |
√ |
√ |
EventType.NodeCreated |
|
√ |
√ |
|
EventType.NodeDeleted |
|
√ |
√ |
|
EventType.NodeDataChanged |
|
√ |
√ |
|
EventType.NodeChildrenChanged |
|
|
|
√
|
b. 出现session expired,需要重建zookeeper connector,对应的watcher会失效。因为watcher在client的存储是和对应的zookeeper client绑定,不同的client有不同的watcher列表。
- 大小: 64.4 KB
- 大小: 168.6 KB
分享到:
相关推荐
NULL 博文链接:https://xkorey.iteye.com/blog/2204495
zookeeper-watcher-demo zookeeper wather demo 示例说明:zookeeper server端,client端每100毫秒写入数据,另一个client端watch节点数据变化 监听的结果是得到的数值是连续的、和数据生成端是一致的,并没有出现...
zookeeper的watcher机制,服务端和客户端你的源码流程,个人总结,个人复习使用
如果在创建znode时Flag设置为EPHEMERAL,那么当创建这个znode的节点和Zookeeper失去连接后,这个znode将不再存在在Zookeeper里,Zookeeper使用Watcher察觉事件信息。当客户端接收到事件信息,比如连接超时、节点数据...
Zookeeper Watcher 机制 — 数据变更通知7. 客户端注册 Watcher 实现8. 服务端处理 Watcher 实现9. 客户端回调 Watcher10. ACL 权限控制机制11. Chroot 特性12. 会话管理13. 服务器角色14. Zookeeper 下 Server ...
//注册监听//修改节点的值触发监ZooKeeper API 的初始化过程转载请注明《咕泡学院》,建议自己分析一遍在创建一个 ZooKeeper 客户端对象实例
ZkClient是Github上一个开源的ZooKeeper客户端。ZkClient在ZooKeeper原生 API接口之上进行了包装,是一个更加易用的ZooKeeper客户端。同时,ZkClient在内部实现了诸如Session超时重连、Watcher反复注册等功能。
3.关于Failover/LoadBalance,由于zookeeper的watcher,当服务端不可用是及时通知客户端,并移除不可用的服务节点,而LoadBalance有很多算法,这里我们采用随机加权方式,也是常有的负载算法,至于其他的算法介绍...
Curator是Netflix公司开源的一套ZooKeeper客户端框架,Curator解决了很多ZooKeeper客户端非常底层的细节开发工作,包括连接重连、反复注册Watcher和NodeExistsException异常等,实现了Fluent风格的API接口,目前已经...
该项目使用了 Apache ZooKeeper .NET async Client 组件,除提供了基本的zk操作,还额外封装了常用的功能以便让.net开发者更好的使用zookeeper。 提供的功能 session过期重连 永久watcher 递归删除...
用于zookeeper写日志的目录要有足够大小,并且强烈建议在单独的磁盘(挂载点)上,这是影响ZK性能最大因素之一。 连接数。 注册的Watcher数。 ZNode是否可读,可写。 ZK事件通知的延时是否过大。 围绕以上几点展开,...
1. 一次性 无论是服务端还是客户端,一旦一个 Watcher 被 触 发 ,Zookeeper 都会将其从相应的存 2. 客户端串行执行 客户端 Watche
HRegionServer也会把自己以临时节点(Ephemeral)的方式注册到Zookeeper中,使得HMaster可以随时感知到各个HRegionServer的存活状态,同时,一旦HMaster出现问题,会重新选举出一个HMaster来运行,从而避免了HMaster...
配置维护大型分布式场景中,对相同配置的集群服务器集中进行配置管理,各服务器在zookeeper中注册watcher监听,发布者更新配置后,zookeeper向订
目录导航前言数据存储基于Java API初探zookeeper的使用事件机制如何注册事件机制watcher 事件类型什么样的操作会产生什么类型的事件呢?事务的实现原理深入分析Watcher机制的实现原理ClientCnxn 初始化客户端通过 ...
通过java客户端创建zk节点,变更节点,利用zk的watcher机制测试zk集群下的数据一致性,事务锁等机制。
Zookeeper使用Watcher察觉事件信息,当客户端接收到事件信息,比如连接超时,节点数据改变,子节点改变,可以调用相应的行为来处理数据。Zookeeper的Wiki页面展示了如何使用Zookeeper来处理事件通知,队列,优先队列...