设为首页 收藏本站
查看: 853|回复: 0

[经验分享] Zookeeper Client简介

[复制链接]

尚未签到

发表于 2019-1-8 08:22:51 | 显示全部楼层 |阅读模式
  直接使用zk的api实现业务功能比较繁琐。因为要处理sessionloss,sessionexpire等异常,在发生这些异常后进行重连。又因为ZK的watcher是一次性的,如果要基于wather实现发布/订阅模式,还要自己包装一下,将一次性订阅包装成持久订阅。另外如果要使用抽象级别更高的功能,比如分布式锁,leader选举等,还要自己额外做很多事情。这里介绍下ZK的两个第三方客户端包装小工具,可以分别解决上述小问题。
  一、zkClient
zkClient主要做了两件事情。一件是在sessionloss和sessionexpire时自动创建新的ZooKeeper实例进行重连。另一件是将一次性watcher包装为持久watcher。后者的具体做法是简单的在watcher回调中,重新读取数据的同时再注册相同的watcher实例。
  zkClient简单的使用样例如下:
public static void testzkClient(final String serverList) {
ZkClient zkClient4subChild = new ZkClient(serverList);
zkClient4subChild.subscribeChildChanges(PATH, new IZkChildListener() {
@Override
public void handleChildChange(String parentPath, List currentChilds) throws Exception {
System.out.println(prefix() + "clildren of path " + parentPath + ":" + currentChilds);
}
});  上面是订阅children变化,下面是订阅数据变化
zkClient4subData.subscribeDataChanges(PATH, new IZkDataListener() {
@Override
public void handleDataChange(String dataPath, Object data) throws Exception {
System.out.println(prefix() + "Data of " + dataPath + " has changed");
}
@Override
public void handleDataDeleted(String dataPath) throws Exception {
System.out.println(prefix() + dataPath + " has deleted");
}
});  订阅连接状态的变化:
ZkClient zkClient4subStat = new ZkClient(serverList);
zkClient4subStat.subscribeStateChanges(new IZkStateListener() {
@Override
public void handleNewSession() throws Exception {
System.out.println(prefix() + "handleNewSession()");
}
@Override
public void handleStateChanged(KeeperState stat) throws Exception {
System.out.println(prefix() + "handleStateChanged,stat:" + stat);
}
});  下面表格列出了写操作与ZK内部产生的事件的对应关系:
eventFor“/path”eventFor“/path/child”create(“/path”)EventType.NodeCreatedNAdelete(“/path”)EventType.NodeDeletedNAsetData(“/path”)EventType.NodeDataChangedNAcreate(“/path/child”)EventType.NodeChildrenChangedEventType.NodeCreateddelete(“/path/child”)EventType.NodeChildrenChangedEventType.NodeDeletedsetData(“/path/child”)NAEventType.NodeDataChanged  而ZK内部的写事件与所触发的watcher的对应关系如下:
eventFor“/path”defaultWatcherexists
(“/path”)
getData
(“/path”)
getChildren
(“/path”)
EventType.None√√√√EventType.NodeCreated√√EventType.NodeDeleted√(不正常)√EventType.NodeDataChanged√√EventType.NodeChildrenChanged√  综合上面两个表,我们可以总结出各种写操作可以触发哪些watcher,如下表所示:
“/path”“/path/child”existsgetDatagetChildrenexistsgetDatagetChildrencreate(“/path”)delete(“/path”)setData(“/path”)create(“/path/child”)delete(“/path/child”)setData(“/path/child”)  如果发生sessionclose、authFail和invalid,那么所有类型的wather都会被触发
  zkClient除了做了一些便捷包装之外,对watcher使用做了一点增强。比如subscribeChildChanges实际上是通过exists和getChildren关注了两个事件。这样当create(“/path”)时,对应path上通过getChildren注册的listener也会被调用。另外subscribeDataChanges实际上只是通过exists注册了事件。因为从上表可以看到,对于一个更新,通过exists和getData注册的watcher要么都会触发,要么都不会触发。
  zkClient地址:https://github.com/sgroschupf/zkclient
Maven工程中使用zkClient需要加的依赖:
<dependency>
<groupId>zkclient</groupId>
<artifactId>zkclient</artifactId>
<version>0.1</version>
</dependency>  二、menagerie
  menagerie基于Zookeeper实现了java.util.concurrent包的一个分布式版本。这个封装是更大粒度上对各种分布式一致性使用场景的抽象。其中最基础和常用的是一个分布式锁的实现:
org.menagerie.locks.ReentrantZkLock,通过ZooKeeper的全局有序的特性和EPHEMERAL_SEQUENTIAL类型znode的支持,实现了分布式锁。具体做法是:不同的client上每个试图获得锁的线程,都在相同的basepath下面创建一个EPHEMERAL_SEQUENTIAL的node。EPHEMERAL表示要创建的是临时znode,创建连接断开时会自动删除;SEQUENTIAL表示要自动在传入的path后面缀上一个自增的全局唯一后缀,作为最终的path。因此对不同的请求ZK会生成不同的后缀,并分别返回带了各自后缀的path给各个请求。因为ZK全局有序的特性,不管client请求怎样先后到达,在ZKServer端都会最终排好一个顺序,因此自增后缀最小的那个子节点,就对应第一个到达ZK的有效请求。然后client读取basepath下的所有子节点和ZK返回给自己的path进行比较,当发现自己创建的sequentialnode的后缀序号排在第一个时,就认为自己获得了锁;否则的话,就认为自己没有获得锁。这时肯定是有其他并发的并且是没有断开的client/线程先创建了node。
  基于分布式锁,还实现了其他业务场景,比如leader选举:
publicstaticvoidleaderElectionTest(){
ZkSessionManagerzksm=newDefaultZkSessionManager(“ZK-host-ip:2181″,5000);
LeaderElectorelector=newZkLeaderElector(“/leaderElectionTest”,zksm,Ids.OPEN_ACL_UNSAFE);
if(elector.nominateSelfForLeader()){
System.out.println(“Trytobecometheleadersuccess!”);
}
}
  java.util.concurrent包下面的其他接口实现,也主要是基于ReentrantZkLock的,比如ZkHashMap实现了ConcurrentMap。具体请参见menagerie的API文档
  menagerie地址:https://github.com/openUtility/menagerie
Maven工程中使用menagerie需要加的依赖:
<dependency>
<groupId>org.menagerie</groupId>
<artifactId>menagerie</artifactId>
<version>1.1-SNAPSHOT</version>
</dependency>



运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-660548-1-1.html 上篇帖子: Zookeeper 集群的安装与部署 下篇帖子: zookeeper 工具类
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表