ZooKeeper Java API编程实例分析编程实例分析
本文主要通过实例给大家详细分析了ZooKeeper用JAVA实现API编程的知识要点。
本实例我们用的是java3.4.6版本,实例方便大家学习完后有不明白的可以在留言区讨论。
开发应用程序的ZooKeeper Java绑定主要由两个Java包组成:
org.apache.zookeeper
org.apache.zookeeper.data
org.apache.zookeeper包由ZooKeeper监视的接口定义和ZooKeeper的各种回调处理程序组成。 它定义了ZooKeeper客户端类库的主要类以及许多ZooKeeper事件类型和状态的静态定义。
org.apache.zookeeper.data包定义了与数据寄存器(也称为znode)相关的特性,例如访问控制列表(ACL),IDs,stats等。
ZooKeeper Java API中的org.apache.zookeeper.server,org.apache.zookeeper.server.quorum和org.apache.zookeeper.server.upgrade包是服务器实现的一部分。 org.apache.zookeeper.client包用于查
询ZooKeeper服务器的状态。
一一 准备开发环境准备开发环境
Apache ZooKeeper是一个复杂的软件,因此它需要运行许多其他类库。 依赖库作为jar文件在ZooKeeper发行版中附带在lib目录中。 核心ZooKeeper jar文件名字为zookeeper-3.4.6.jar,位于主目录下。
要开发Java的ZooKeeper应用程序,我们必须设置指向ZooKeeper jar的类路径,以及ZooKeeper所依赖的所有第三方库。在 bin 目录下有一个 zkEnv.sh文件,可以用来设置CLASSPATH。
我们需要将脚本如下设置,在命令行中执行以下语句:
$ ZOOBINDIR=${ZK_HOME}/bin
$ source ${ZOOBINDIR}/zkEnv.sh
shell变量ZK_HOME被设置为安装ZooKeeper的路径,在我的设置中,它是/usr/share/zookeeper。 之后,CLASSPATH变量被正确设置,在我的系统中,如下所示:
$ echo $CLASSPATH
/usr/share/zookeeper-3.4.6/bin/../build/classes :/usr/share/zookeeper-3.4.6/bin/../build/lib/*.jar :/usr/share/zookeeper-3.4.6/bin/../lib/slf4j-log4j12-1.6.1.jar :/usr/share/zookeeper-3.4.6/bin/../lib/slf4j-api-1.6.1.jar :/usr/share/zookeeper-3.4.6/bin/../lib/netty-3.7.0.Final.jar :/usr/share/zookeeper-3.4.6/bin/../lib/log4j-1.2.16.jar :/usr/share/zookeeper-3.4.6/bin/../lib/jline-0.9.94.jar :/usr/share/zookeeper-3.4.6/bin/../zookeeper-3.4.6.jar :/usr/share/zookeeper-3.4.6/bin/../src/java/lib/*.jar :/usr/share/zookeeper-3.4.6/bin/../conf:
在Windows操作系统中,需要运行zkEnv.cmd脚本。 现在可以使用CLASSPATH变量来编译和运行使用ZooKeeper API编写的Java程序。 可以在Uni/Linux中的主目录的.bashrc文件中找到zkEnv.sh脚
本,避免每次启动shell会话时都采用它。
二二 第一个第一个ZooKeeper程序程序
为了引入ZooKeeper Java API,让我们从一个非常简单的程序开始,它可以连接到localhost中的ZooKeeper实例,如果连接成功,它将在ZooKeeper名称空间的根路径下打印znode的列表。
这个程序的代码如下所示:
/*Our First ZooKeeper Program*/
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.ZooKeeper;
public class HelloZooKeeper {
public static void main(String[] args) throws IOException {
String hostPort = "localhost:2181";
String zpath = "/";
List <String> zooChildren = new ArrayList<String>();
ZooKeeper zk = new ZooKeeper(hostPort, 2000, null);
if (zk != null) {
try {
zooChildren = zk.getChildren(zpath, false);
System.out.println("Znodes of '/': ");
for (String child: zooChildren) {
//print the children
System.out.println(child);
}
} catch (KeeperException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
在构建和执行前面的代码片段之前,让我们来看看它具体做了什么。代码从导入语句开始。使用这些语句,我们导入了程序各个组件所需的包。如前所述,org.apache.zookeeper包包含客户端与
ZooKeeper服务器进行交互所需的所有类和接口。在导入包之后,定义了一个名为HelloZooKeeper的类。由于我们要连接到在同一系统中运行的ZooKeeper实例,在main方法中将主机和端口字符串定义
为localhost:2181。代码行zk = new ZooKeeper(hostPort, 2000, null)调用ZooKeeper构造方法,该构造方法尝试连接到ZooKeeper服务器并返回一个引用。对于连接到ZooKeeper服务器实例并维护该连
接的客户端程序,需要维护一个实时会话。在此例中,构造方法实例化的zk对象返回的引用表示这个会话。 ZooKeeper API是围绕这个引用构建的,每个方法调用都需要一个引用来执行。
ZooKeeper类的构造方法使用以下代码创建ZooKeeper实例的引用:
ZooKeeper(String connectString, int sessionTimeout, Watcher watcher)
使用的参数含义如下:
connectString:以逗号分隔的主机:端口号列表,每个对应一个ZooKeeper服务器。 例如,10.0.0.1:2001,10.0.0.2:2002和10.0.0.3:2003表示三个节点的ZooKeeper ensemble的有效的主机:端口匹配
对。 sessionTimeout:这是以毫秒为单位的会话超时时间。这是ZooKeeper在宣布session结束之前,没有从客户端获得心跳的时间。 watcher:一个watcher对象,如果创建,当状态改变和发生节点事
件时会收到通知。这个watcher对象需要通过一个用户定义的类单独创建,通过实现Watcher接口并将实例化的对象传递给ZooKeeper构造方法。客户端应用程序可以收到各种类型的事件的通知,例如连
接丢失、会话过期等。
ZooKeeper Java API定义了另外带有三个参数的构造方法,以指定更高级的操作。代码如下:
ZooKeeper(String connectString, int sessionTimeout, Watcher watcher, boolean canBeReadOnly)
在ZooKeeper类的上面的构造方法中,如果设置为true,boolean canBeReadOnly参数允许创建的客户端在网络分区的情况下进入只读模式。只读模式是客户端无法找到任何多数服务器的场景,但有一
个可以到达的分区服务器,以只读模式连接到它,这样就允许对服务器的读取请求,而写入请求则不允许。客户端继续尝试在后台连接到大多数服务器,同时仍然保持只读模式。分区服务器仅仅是
ZooKeeper组的一个子集,它是由于集群中的网络分配而形成的。大多数服务器构成了ensemble中的大多数quorum。
以下构造方法显示了两个附加参数的定义:
ZooKeeper(String connectString, int sessionTimeout, Watcher watcher, long sessionId, byte[] sessionPasswd)
这个构造方法允许ZooKeeper客户端对象创建两个额外的参数:
sessionId:在客户端重新连接到ZooKeeper服务器的情况下,可以使用特定的会话ID来引用先前连接的会话 sessionPasswd:如果指定的会话需要密码,可以在这里指定
以下构造方法是前两个调用的组合:
ZooKeeper(String connectString, int sessionTimeout,Watcher watcher, long sessionId, byte[] sessionPasswd,boolean canBeReadOnly)
此构造方法是前两个调用的组合,允许在启用只读模式的情况下重新连接到指定的会话。
Note
ZooKeeper类的详细Java API文档可以在http://zookeeper.apache.org/doc/r3.4.6/api/index.html上查询。
现在,回到我们的ZooKeeper程序。 在调用构造方法后,如果连接成功,我们将得到ZooKeeper服务器的引用。 我们通过下面的代码将引用传递给getChildren方法:
zooChildren = zk.getChildren(zpath, false)
ZooKeeper类的getChildren(String path,boolean watch)方法返回给定路径上znode的子级列表。 我们只是迭代这个方法返回的列表,并将字符串打印到控制台。
将程序命名为HelloZooKeeper.java,并编译我们的程序如下: