赞
踩
本文着重介绍如何部署一个Zookeeper以及如何顺利运行起来。以及可能遇到的问题和解决方法、客户端脚本的使用、Java客户端API使用。最后,介绍了ZkClient和Curator这两种开源客户端。
目录
如何使用三台机器搭建一个Zookeeper集群?
首先需要假设已经准备好三台互相联网的Linux机器,IP地址分别为
1. 准备配置Java环境,确保已经安装Java1.6或更高版本的JDK
2. 下载Zookeeper安装包,下载成功后,解压到一个目录里面,例如/opt/zookeeper-3.4.4/目录下,同时在下文中,我们使用%ZK_HOME%代表该目录。
3. 配置文件zoo.cfg:
初次使用Zookeeper,需要将%ZK_HOME%/conf目录下的zoo_sample.cfg文件重命名为zoo.cfg,并且按照以下代码进行简单配置。
关于Zookeeper的参数配置,在集群中的每台机器都需要感知到整个集群是由哪几台机器组成的,在配置文件中,可以进行这样的配置。(例如最后3行)其中,id用来标记该机器在集群中的序号。同时在每台机器上,我们都需要在数据目录下创建一个myid文件,该文件只有一行内容,并且是一个数字,对应于每台机器的Server ID数字。
在Zookeeper的设计中,集群中所有机器上 zoo.cfg文件的内容都应该是一致的。因此最好使用SVN或GIT把此文件管理起来,确保每个机器都能共享到一份相同的配置。
myid文件中只有一个Server ID代表自己的编号。注意每个机器的myid都不同,并且和自己所在机器的server.id的id值对应上。
4. 创建myid文件
在dataDir所配置的目录下,创建一个名为myid的文件,在该文件的第一行写上自身编号。
5. 按照相同步骤,为所有机器都配置好zoo.cfg和myid文件。
6. 启动服务器
至此,所有选项已经配置完毕,使用%ZK_HOME%/bin目录下的zkServer.sh脚本进行服务器的启动,如下:
7. 验证服务器
启动完成后,可以使用如下命令来检查服务器启动是否正常:
上面就是使用Telnet方式,使用stat命令进行服务器启动的验证,如果出现和上面类似的输出信息,就说明服务器已经正常启动了。
上文集群模式中,已经完成了一个Zookeeper集群的搭建了。幸运的是,Zookeeper支持单机部署,只要启动一台Zookepper机器,就可以提供正常服务了。
其实,单机模式只是一种特殊的集群模式--只有一台机器的集群。单机模式的部署步骤和集群模式的部署步骤基本一致,只是在zoo.cfg文件的配置上有些差异。(唯一的区别就在列表上)在单机模式的文件中,只有server.1这一项。修改完这个文件后,就可以启动服务器了。
上文中,集群和单机两种模式下,基本完成了分别针对生产环境和开发环境Zookeeper服务的搭建,已经可以满足绝大多数场景了。
但是还是有一种情况就是:手上有且只有一个比较好的机器,如果作为单机模式部署,资源明显有点浪费;如果想按照集群模式来部署的话,需要借助硬件上的虚拟化技术,把一台物理机器转换成几台虚拟机,不过这样操作成本太高。所幸,和其他分布式系统(例如Hadoop)一样,Zookeeper也允许你在一台机器上完成一个伪集群的搭建。
伪集群,用一句话说就是,集群所有的机器都在同一台机器上,但是还是以集群的特性对外提供服务。这种模式和集群模式非常类似,只是把zoo.cfg做了如下修改
在zoo.cfg配置中,每一行的机器列表配置都是同一个IP地址,但是后面的端口配置已经不一样了。这其实不难理解,在同一台机器上启动多个进程,就必须绑定不同的接口。
本部分重点说明如何启动与停止Zookeeper服务,如何解决在Zookeeper服务启动阶段出现的常见异常问题。
启动服务
停止服务
在启动的时候,通常会碰到一些异常。
1. Address already in use:端口被占用
2. No space left on device:磁盘没有剩余空间(通常做法是清理磁盘,加上用量监控及日志自动清理)
3. Invalid config,exiting abnormally:无法找到myid文件,创建一个即可
4. Cannot open channel to 2 at election address /122.228.242.241:3888:集群中其它机器Leader选举端口未开(由于虽然当前机器启动了,但是其他机器还未启动完成,因此无法和其他机器在相应端口上进行连接),需要快速启动其他机器。
现在就已经搭建起了一个能够正常运行的Zookeeper集群了
现在已经搭建起了一个能够正常运行的Zookeeper集群了,接下来学习如何使用客户端对Zookeeper进行操作。
首先客户端需要连接上本地的Zookeeper服务器:进入到Zookeeper的bin目录后,直接执行:sh zkCli.sh 就成功连接上本地的Zookeeper服务器。
1. 使用create命令创建一个Zookeeper节点
2. 使用ls或get命令进行读取
3. 使用set命令,更新指定节点的内容
4. 使用delete命令删除Zookeeper上的指定节点
Zookeeper作为一个分布式系统框架,主要用来解决分布式数据一致性问题,提供了简单的分布式原语,并且对多种编程语言提供了API。
public ZooKeeper(String connectString, int sessionTimeout, Watcher watcher, boolean canBeReadOnly)
客户端可以通过创建一个ZooKeeper(org.apache.zookeeper.Zookeeper)实例来连接ZooKeeper服务器。Zookeeper的四种构造方法如下:
使用任意一个构造方法都可以顺利完成与Zookeeper服务器的会话(Session)创建,每个参数的说明:
扩展构造方法
Zookeeper还提供了扩展的构造方法,以支持更多高级配置,如连接超时设置、重试策略等。以下是一个扩展构造方法的例子:
public ZooKeeper(String connectString, int sessionTimeout, Watcher watcher, boolean canBeReadOnly)
小结
Zookeeper的构造方法参数用于指定的连接信息,会话超时时间和时间处理机制等,通过这些参数,客户端可以灵活的配置和连接到Zookeeper集群,使用Watcher机制处理节点变更事件,并支持高级功能如会话恢复和只读模式
客户端可以通过Zookeeper的API来创建一个数据节点,有两个接口。这两个接口分别以同步和异步方式创建节点,以满足不同的应用场景。同步方式适用于需要立即获取结果的简单场景,代码简单但可能会阻塞线程。异步方式适用于需要高并发处理的复杂场景,性能更优但是代码复杂度较高。选择哪种方式取决于具体的应用需求和系统设计。
Zookeeper中创建会话和创建节点的主要区别是,创建会话是初始化客户端与服务器连接的过程,而创建节点是实际在Zookeeper中存储数据和实现分布式协调的操作。会话是所有操作的基础,而节点创建是具体的应用场景。
客户端可以用Zookeeper的API来删除一个节点,有两个接口,这两个API分别是同步和异步的删除接口。Zookeeper中,只允许删除叶子节点。也就是说,如果一个节点存在至少一个子节点的话,那么该节点无法被直接删除,必须先删除点其所有子节点。
读取数据,包括子节点列表的获取和节点数据的获取。Zookeeper分别提供了不同的API来获取数据。客户端可以通过Zookeeper的API来获取一个节点的所有子节点,即getChildren,有如下8个接口可以供使用:
其中包含了同步和异步的接口。
客户端可以通过Zookeeper的API来更新一个节点的数据内容,有如下两个接口,也是分别为同步和异步方式。setData
客户端可以通过Zookeeper的API来检测一个接口是否存在,这四个接口也是分别用同步和异步的方式来检测的:
该接口主要用于检测节点是否存在,返回值是一个stat对象。另外,如果在调用接口时注册Watcher的话,还可以对节点是否存在进行监听,一旦节点被创建、被删除或是数据被更新,都会通知客户端。
在Zookeeper的实际使用中,我们的做法往往是搭建一个共用的Zookeeper集群,统一为若干个应用提供服务。在这种情况下,不同的应用之间往往是不会存在共享数据的使用场景的,因此需要解决不同应用之间的权限问题。
Zookeeper提供了ACL的权限控制机制,简单的讲,就是通过设置Zookeeper服务器上的数据节点的ACL,来控制客户端对该数据节点的访问权限:如果一个客户端符合该ACL控制,那么就可以对其进行访问,否则无法操作。
针对这样的控制机制,Zookeeper提供了多种权限控制模式(Scheme),分别为world、auth、digest、ip和super。
开发人员如果要使用Zookeeper的权限控制功能,需要在完成Zookeeper会话创建后,给该会话添加上相关的权限信息(AuthInfo)。Zookeeper客户端提供了相应的API接口来进行权限信息的设置,即addAuthInfo(String sheme, byte auth) -> 为当前的Zookeeper会话添加权限信息。
上一节中,讲解了如何使用Zookeeper的Java客户端来进行一些基本操作,如创建会话、创建节点、读取数据、更新数据、删除节点和检测节点是否存在等。本节中,我们将围绕ZkClient和Curator这两个开源的Zookeeper客户端产品,来进一步看看如何更好地使用Zookeeper
ZkClient是一个更易用的Zookeeper客户端。同时,ZkClient在内部实现了诸如Session超时重连、Watcher反复注册等功能,使得Zookeeper客户端的这些繁琐细节对开发者透明。
本节中将从创建会话、创建节点、读取数据、更新数据、删除节点和检测节点是否存在等方面来介绍如何使用ZkClient这个Zookeeper客户端。
(1) 首先添加ZkClient的Maven依赖
(2) 创建会话:使用ZkClient接口创建会话,很多参数与Zookeeper的原生参数一致(在使用Zookeeper原生API创建会话的时候,是一个异步的过程,开发人员需要自己等待处理。而ZkClient通过内部包装,将这个异步的会话创建过程同步化了,对于开发者更为方便)
(3) Zookeeper的节点内容只支持字符数组(byte[]),不负责为节点内的内容序列化,需要开发人员自己使用序列化工具进行序列化和反序列化。而ZkClient实现了一个接口,允许用户传入一个序列化实现,例如Hessian或Kryo,默认情况下,ZkClient使用Java自带的默认序列化方式进行对象的序列化)
(4) ZkClient与原生Zookeeper的最大区别,就是在ZkClient的构造方法中,不再提供传入Watcher对象的参数了。那么,ZkClient如何去监听服务端的相关事宜呢?ZkClient引入了大多数Java程序都使用过的Listener来实现Watcher注册,这样的用法更贴近Java工程师的开发习惯。
(5) 创建节点:原生接口只允许传入字符数组作为对象,而ZkClient由于支持自定义序列化器,可以传入复杂对象作为参数。ZkClient将各种不同节点的创建使用不同的方法名字进行区分,在创建节点的时候,不需要再去判定父节点是否存在并进行一系列的相关操作,而是可哟通过createParents参数,在内部递归建立父节点。此外,还支持异步创建节点的方法。
(6) 删除节点:原生Zookeeper只允许删除叶子结点。但是真正的产品使用中,我们的节点层级往往比较复杂,通常在4层左右。如果每层都逐层遍历来删除节点,会非常繁琐。在ZkClient中,deleteRecursive这个接口将自动帮我们完成逐层遍历删除节点的工作,为开发人员带来便利。
(7) 读取数据:在ZkClient中,可以通过getChildren获取指定节点的子节点列表,ZkClient只提供了一个对外API,用于获取指定节点的子节点列表。这个API的返回值是子节点的相对路径。在ZkClient中,可以使用readData来获取指定节点的数据内容。
- 和Zookeeper原生API相比,ZkClient提供的API没有了Watcher注册的功能,在“创建会话”部分中我们已经提到,ZkClient中引入了Listener的概念,客户端可以通过注册相关的时间监听来实现对Zookeeper服务端事件的订阅。在获取子节点接口列表这个接口上,可以通过subscribeChildChanges接口来进行注册监听,传入的IZkChildListener接口,只有一个接口方法handleChildChange,用来处理服务端发送过来的事件通知。
- 另外,和Zookeeper原生提供的Watcher不同的是,ZkClient的Listener不是一次性的,客户端只需要注册一次就会一直生效
(8) 更新数据:在ZkClient中,可以通过writeData这个API来更新指定节点的数据。可以通过exists这个API来检测指定节点是否存在。
和ZkClient一样,Curator解决了很多Zookeeper客户端非常底层的细节开发共工作,包括连接重连、反复注册Watcher和NodeExistsException异常等,是全世界使用最广泛的Zookeeper客户端之一。
除了封装一些开发人员不需要关注的底层细节之外,Curator还在Zookeeper的原生API的基础上进行包装,提供了一套易用性和可读性更强的Fluent风格的客户端API框架。
除此之外,Curator中还提供了Zookeeper各种应用场景(Recipe,如共享锁服务、Master选举机制和分布式计数器)的抽象封装。
(1) 首先要添加Curator的Maven依赖
(2) 创建会话:
Curator提供的API接口在设计上最大的亮点在于其遵循了Fluent的设计风格
(3) 创建节点
(4) 删除节点
(5) 读取数据
(6) 更新数据
Curator引入了BackgroundCallback接口,用来处理异步接口调用之后服务端返回的结果信息。
本章主要围绕Zookeeper服务的使用展开,对Zookeeper的基本使用方式进行了全面的讲解。首先,分别从集群、单机和伪集群三种模式介绍如何部署与运行一个可用的Zookeeper服务,同时介绍了在Zookeeper服务部署与运行过程中的系统环境配置以及对于常见异常问题的解决。接下来,主要围绕Zookeeper自带的客户端脚本,就Zookeeper服务的基本使用方式向读者进行了介绍。最后,通过对Zookeeper提供的Java API接口以及开源客户端ZkClient和Curator的分别讲解以及源代码示例的展示,帮助读者更好地在Java应用程序中使用Zookeeper服务。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。