`
longgangbai
  • 浏览: 7332115 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论
阅读更多

直接使用zk的api实现业务功能比较繁琐。因为要处理session loss,session expire等异常,在发生这些异常后进行重连。又因为ZK的watcher是一次性的,如果要基于wather实现发布/订阅模式,还要自己包装一下,将一次性订阅包装成持久订阅。另外如果要使用抽象级别更高的功能,比如分布式锁,leader选举等,还要自己额外做很多事情。这里介绍下ZK的两个第三方客户端包装小工具,可以分别解决上述小问题。

一、 zkClient
zkClient主要做了两件事情。一件是在session loss和session expire时自动创建新的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变化,下面是订阅数据变化

		ZkClient zkClient4subData = new ZkClient(serverList);
		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内部产生的事件的对应关系:

  event For “/path”event For “/path/child”
create(“/path”) EventType.NodeCreated NA
delete(“/path”) EventType.NodeDeleted NA
setData(“/path”) EventType.NodeDataChanged NA
create(“/path/child”) EventType.NodeChildrenChanged EventType.NodeCreated
delete(“/path/child”) EventType.NodeChildrenChanged EventType.NodeDeleted
setData(“/path/child”) NA EventType.NodeDataChanged

而ZK内部的写事件与所触发的watcher的对应关系如下:

event For “/path”defaultWatcherexists
(“/path”)
getData
(“/path”)
getChildren
(“/path”)
EventType.None
EventType.NodeCreated    
EventType.NodeDeleted   √(不正常)  
EventType.NodeDataChanged    
EventType.NodeChildrenChanged      

综合上面两个表,我们可以总结出各种写操作可以触发哪些watcher,如下表所示:

  “/path”“/path/child”   existsgetDatagetChildrenexistsgetDatagetChildren
create(“/path”)        
delete(“/path”)      
setData(“/path”)        
create(“/path/child”)      
delete(“/path/child”)    
setData(“/path/child”)        

如果发生session close、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进行比较,当发现自己创建的sequential node的后缀序号排在第一个时,就认为自己获得了锁;否则的话,就认为自己没有获得锁。这时肯定是有其他并发的并且是没有断开的client/线程先创建了node。

基于分布式锁,还实现了其他业务场景,比如leader选举:
public static void leaderElectionTest() {
ZkSessionManager zksm = new DefaultZkSessionManager(“ZK-host-ip:2181″, 5000);
LeaderElector elector = new ZkLeaderElector(“/leaderElectionTest”, zksm, Ids.OPEN_ACL_UNSAFE);
if (elector.nominateSelfForLeader()) {
System.out.println(“Try to become the leader success!”);
}
}

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>
转载自:
http://rdc.taobao.com/team/jm/archives/1047
分享到:
评论

相关推荐

    zookeeper client依赖的jar包

    zookeeper client依赖jar包,核心依赖的jar包,生产者和消费者必不可少的

    ZooKeeper3.7.0(ZooKeeper-client)编译的头文件和库

    linux下编译zookeeper3.7.0出的头文件和库: proto.h recordio.h zookeeper.h zookeeper.jute.h zookeeper_log.h zookeeper_version.h libzookeeper_mt.a libzookeeper_mt.la libzookeeper_mt.so libzookeeper_mt....

    springboot-zookeeper-client.rar

    SpringBoot与Zookeeper客户端集成详解 在分布式系统中,Zookeeper作为一个高可用的分布式协调服务,扮演着重要的角色。它提供了诸如配置管理、命名服务、分布式锁、集群节点监控等多种功能。SpringBoot作为轻量级的...

    基于Java语言实现的ZooKeeperClient设计源码,用于监控ZooKeeper节点情况

    该项目是一款基于Java语言实现的ZooKeeperClient设计源码,专注于监控ZooKeeper节点状况。项目包含61个文件,涵盖了34个HTML文件、11个JAR包、6个Java源文件、4个GIF图片、2个Git忽略文件、1个构建路径文件和1个项目...

    zookeeper-server-client 简单例子

    **Zookeeper 概述** Zookeeper 是一个分布式协调服务,由 Apache 开发并维护,它为分布式应用程序提供了高效且可靠的命名服务、配置管理、集群同步、分布式锁等核心功能。Zookeeper 的设计目标是简化分布式环境下的...

    ZooKeeper 客户端的使用(二).

    在分布式系统领域,ZooKeeper 是一个至关重要的组件,它为分布式应用程序提供了高效且可靠的协调服务。本篇文章将深入探讨 ZooKeeper 客户端的使用,这是继上一篇文章后的第二部分,我们将继续学习如何与 ZooKeeper ...

    超级好用的Zookeeper可视化工具

    **Zookeeper可视化工具详解** 在分布式系统管理中,Apache ZooKeeper是一个至关重要的组件,它提供了一个集中式的、高可用的服务,用于协调分布式应用。Zookeeper的主要功能包括命名服务、配置管理、集群同步、分组...

    zookeeper架构简介

    Zookeeper架构简介 Zookeeper是一个开源的分布式应用协调服务,主要应用于大数据开发中的统一命名服务、统一配置管理、统一集群管理、服务器节点动态上下线、软负载均衡等场景。该框架相当于大数据框架中的润滑剂。...

    node-zookeeper-client:适用于Node.js的纯JavaScript ZooKeeper客户端

    节点动物园管理员客户端 用于纯JavaScript 客户端模块。 该模块的设计类似于ZooKeeper ...var client = zookeeper . createClient ( 'localhost:2181' ) ; var path = process . argv [ 2 ] ; client . once ( 'conn

    Zookeeper_安装和配置

    - `clientPort`:客户端连接 Zookeeper 服务器的端口号。 4. **启动**:完成配置后,通过执行 `bin/zkServer.sh start` 来启动 Zookeeper 服务器。 5. **连接**:使用 `bin/zkCli.sh -server localhost:4180` 命令...

    zookeeper linux集群搭建流程

    修改 zookeeper 启动配置文件 zoo.cfg,配置 dataDir、dataLogDir、clientPort,并进行集群配置,例如: server.1=172.19.59.46:2888:3888 server.2=172.19.59.47:2889:3889 server.3=172.19.59.50:2890:3890 其中...

    zookeeper 3.6.3 源码下载

    - `src/main/java/org/apache/zookeeper/client`:客户端的实现,包括连接管理和API调用。 - `src/main/java/org/apache/zookeeper/data`:数据模型相关的类,如ZNode的元数据结构。 - `src/main/java/org/apache/...

    zookeeper集群升级方案

    ### Zookeeper 集群升级方案详解 #### 一、需求背景 随着业务的发展和技术的进步,现有的Zookeeper集群系统版本过低(当前版本为3.3.4),导致某些功能特性无法得到支持或表现不佳,这直接影响到了业务的正常运行...

    zkclient:用C ++编写的Zookeeper SDK包装器

    zkclientc++ wrapper for libzookeeper async api保留了一些assert, 用于在生产环境中发现一些没有预期到的state/event,不过从zookeeper c client源码来看,其他未assert的状态不应出现。搞清楚zookeeper client的...

    Zookeeper双机房容灾方案.pdf

    5. follower收到uptodate消息后,又可以重新接受client的请求,进行服务。 模拟场景3:模拟目的场景概述是指模拟Zookeeper节点的状态信息。操作步骤包括:1. 登入Zookeeper客户端;2. 使用命令stat &lt;node_path&gt; ...

    zookeeper-3.4.12版本

    Zookeeper采用Paxos算法保证了数据的一致性和可靠性,其架构由服务器(Server)和客户端(Client)组成,支持集群模式运行,通常配置为奇数台服务器以确保高可用性。 二、Zookeeper主要功能 1. **配置管理**:集中...

    linux中zookeeper安装包zookeeper-3.4.8.tar

    而端口号(clientPort)则是Zookeeper服务器监听客户端连接的端口。 启动Zookeeper服务,你可以使用`bin/zkServer.sh`脚本。在多节点集群环境中,需要确保每个节点的配置文件一致,并设置正确的集群配置(server.1,...

    zookeeper-solr集群

    在本场景中,我们主要关注如何在Linux环境下搭建一个基于Zookeeper的SolrCloud集群。 首先,我们需要准备必要的软件环境。操作系统选择的是Linux,而Solr服务使用的是版本4.8.1,与之配合的Tomcat服务器是7.0.54...

    CentOS7.0安装zookeeper

    #### 一、Zookeeper简介 Zookeeper 是一个分布式的协调服务框架,它提供了一种高效、可靠的机制来维护集群中的分布式进程之间的协调工作,比如命名服务、配置管理、集群同步等。在分布式系统中,Zookeeper 被广泛...

    zookeeper linux版本

    配置文件中包括了ZooKeeper的数据存储路径(dataDir)、客户端连接端口(clientPort)等关键设置。 3. **创建数据目录**:根据`dataDir`配置的路径,确保该目录存在并可写入,例如`mkdir -p /var/lib/zookeeper`。 4...

Global site tag (gtag.js) - Google Analytics