监听器原理
客户端注册监听它关心的目录节点,当目录节点发生变化(数据改变、节点删除、子目录节点增加删除)时,ZooKeeper会通知客户端。监听机制保证 ZooKeeper保存的任何的数据的任何改变都能快速的响应到监听了该节点的应用程序。
1. 监听机制
监听器流程如下:
- 首先要有一个main()线程。
- 在main线程中创建Zookeeper客户端,这时就会创建两个线程,一个负责网络连接通信(connet),一个负责监听(listener)。
- 通过connect线程将注册的监听事件发送给Zookeeper。
- 在Zookeeper的注册监听器列表中将注册的监听事件添加到列表中。
- Zookeeper监听到有数据或路径变化,就会将这个消息发送给listener线程。
- listener线程内部调用了process()方法。
常见的监听:
- 监听节点数据的变化
- 监听子节点增减的变化
2. 监听事件
Zookeeper中的watch机制(也就是监听),必须客户端先去服务端注册监听,这样事件发送才会触发监听,通知给客户端。
监听的对象是事件,支持的事件类型如下:
- None: 连接建立事件
- NodeCreated:节点创建
- NodeDeleted:节点删除
- NodeDataChanged:节点数据变化
- NodeChildrenChanged:子节点列表变化
- DataWatchRemoved:节点监听被移除
- ChildWatchRemoved:子节点监听被移除
监听常用到的命令有:
sh
#监听节点数据的变化
get -w path
stat -w path
#监听子节点增减的变化
ls -w path
3. 节点的值变化监听
- 在hadoop106主机上注册监听/sanguo节点数据变化
sh
[zk: localhost:2181(CONNECTED) 0] create /sanguo "陈寿"
Created /sanguo
[zk: localhost:2181(CONNECTED) 0] get -w /sanguo
陈寿
- 在hadoop105主机上修改/sanguo节点的数据
sh
[zk: localhost:2181(CONNECTED) 1] set /sanguo "chenshou"
- 观察hadoop106主机收到数据变化的监听
sh
[zk: localhost:2181(CONNECTED) 1]
WATCHER::
WatchedEvent state:SyncConnected type:NodeDataChanged path:/sanguo
- 再次在hadoop105主机上修改/sanguo节点的数据,发现hadoop106主机控制台没变化
sh
[zk: localhost:2181(CONNECTED) 2] set /sanguo "chen"
重要提示
在hadoop103再多次修改/sanguo的值,hadoop104上不会再收到监听。因为watch是一次性的,只能监听一次。想再次监听,需要再次注册。
4. 子节点变化监听(路径变化)
- 在hadoop106主机上注册监听/sanguo节点的子节点变化
sh
[zk: localhost:2181(CONNECTED) 3] ls -w /sanguo
[]
- 在hadoop105主机/sanguo节点上创建子节点
sh
[zk: localhost:2181(CONNECTED) 2] create /sanguo/weiguo "caocao"
Created /sanguo/weiguo
- 观察hadoop106主机收到子节点变化的监听
sh
[zk: localhost:2181(CONNECTED) 4]
WATCHER::
WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/sanguo
- 再次在hadoop105主机/sanguo节点上创建子节点,发现hadoop106就没有收到监听消息了
sh
[zk: localhost:2181(CONNECTED) 1] create /sanguo/shuguo "liubei"
Created /sanguo/shugu
重要提示
同样的,节点的路径变化,也是注册一次性的,生效一次。想多次生效,就需要多次注册。
5. 永久监听
Zookeeper3.6.0版本新增的功能,事件在被触发之后,仍然保留节点上面的监听,可以继续监听ZNode上的变更。
永久监听命令格式:addWatch [-m mode] path
addWatch的作用是针对指定节点添加事件监听,支持两种模式:
PERSISTENT
,持久化订阅,针对当前节点的修改和删除事件,以及当前节点的子节点的删除和新增事件。PERSISTENT_RECURSIVE
,持久化递归订阅(默认),在PERSISTENT的基础上,增加了子节点修改的事件触发,以及子节点的子节点的数据变化都会触发相关事件(满足递归订阅特性)。
- 在hadoop106主机上注册监听/sanguo/shuguo节点的子节点变化
sh
[zk: localhost:2181(CONNECTED) 2] addWatch -m /sanguo/shuguo
- 在hadoop105主机/sanguo/shuguo节点上创建子节点以及变更数据
sh
[zk: localhost:2181(CONNECTED) 0] create -e /sanguo/shuguo/zhugeliang "诸葛亮"
Created /sanguo/shuguo/zhugeliang
[zk: localhost:2181(CONNECTED) 1] create -s /sanguo/shuguo/zhangfei "张飞"
Created /sanguo/shuguo/zhangfei0000000001
[zk: localhost:2181(CONNECTED) 2] create /sanguo/shuguo/guanyu "关羽"
Created /sanguo/shuguo/guanyu
[zk: localhost:2181(CONNECTED) 3] set /sanguo/shuguo/zhugeliang "zgl"
- 观察hadoop106主机收到子节点变化的监听
sh
[zk: localhost:2181(CONNECTED) 3]
WATCHER::
WatchedEvent state:SyncConnected type:NodeCreated path:/sanguo/shuguo/zhugeliang
WATCHER::
WatchedEvent state:SyncConnected type:NodeCreated path:/sanguo/shuguo/zhangfei0000000001
WATCHER::
WatchedEvent state:SyncConnected type:NodeCreated path:/sanguo/shuguo/guanyu
[zk: localhost:2181(CONNECTED) 3]
WATCHER::
WatchedEvent state:SyncConnected type:NodeDataChanged path:/sanguo/shuguo/zhugeliang