8.1 集群环境搭建

【操作目的】

由于在ZooKeeper集群中,会有一个Leader服务器负责管理和协调其他集群服务器,因此服务器的数量通常都是单数,例如3,5,7...等,这样数量为2n+1的服务器就可以允许最多n台服务器的失效。

【操作步骤】

本例中,我们仍然使用三个节点搭建部署ZooKeeper集群,搭建步骤如下:

1.上传ZooKeeper安装文件

在centos01节点中,上传ZooKeeper安装文件zookeeper-3.4.9.tar.gz到目录/opt/softwares/中,并将其解压到目录/opt/modules/,解压命令如下:

tar -zxvf zookeeper-3.4.9.tar.gz -C /opt/modules/

2.编写配置文件

(1)在ZooKeeper安装目录下新建文件夹dataDir,用于存放ZooKeeper数据。

(2)在ZooKeeper安装目录下的conf文件夹中新建配置文件zoo.cfg,加入以下内容:

tickTime=2000
initLimit=10
syncLimit=5
dataDir=/opt/modules/zookeeper-3.4.9/dataDir
clientPort=2181 server.1=centos01:2888:3888
server.2=centos02:2888:3888
server.3=centos03:2888:3888

上述参数说明如下:

initLimit:集群中的Follower服务器初始化连接Leader服务器时能等待的最大心跳数(连接超时时长)。默认为10,即如果经过10个心跳之后Follower服务器仍然没有收到Leader服务器的返回信息,则连接失败。本例中该参数值为5,参数tickTime为2000,则连接超时时长为52000=10秒(即tickTimeinitLimit=10秒)。

syncLimit:集群中的Follower服务器与Leader服务器之间发送消息以及请求/应答时所能等待的最多心跳数。本例中,tickTime的值为2,时长为2*2000=4秒。

server.id:标识不同的ZooKeeper服务器。ZooKeeper可以从“server.id=host:port1:port2”中读取相关信息。其中,id值必须在整个集群中是唯一的,且大小在1到255之间;host是服务器的名称或IP地址;第一个端口(port1)是Leader端口,即该服务器作为Leader时供Follower连接的端口;第二个端口(port2)是选举端口,即选举Leader服务器时供其它Follower连接的端口。

dataDir:ZooKeeper保存数据的目录。

clientPort:客户端连接ZooKeeper服务器的端口,ZooKeeper会监听这个端口,接收客户端的请求。

(3)在配置文件zoo.cfg中的参数dataDir指定的目录下(此处为ZooKeeper安装目录下的dataDir文件夹)新建一个名为myid的文件,这个文件仅包含一行内容,即当前服务器的id值,与参数server.id中的id值相同。本例中,当前服务器(centos01)的id值为1,则应该在myid文件中写入数字1。ZooKeeper启动时会读取该文件,将其中的数据与zoo.cfg里写入的配置信息进行对比,从而获取当前服务器的身份信息。

3.拷贝ZooKeeper安装信息到其它节点

centos01节点安装完成后,需要拷贝整个ZooKeeper安装目录到centos02和centos03节点,命令如下:

scp -r /opt/modules/zookeeper-3.4.9/ hadoop@centos02:/opt/modules/
scp -r /opt/modules/zookeeper-3.4.9/ hadoop@centos03:/opt/modules/

4.修改其它节点配置

拷贝完成后,需要将centos02和centos03节点中的myid文件的值修改为对应的数字,即作出以下操作:

修改centos02节点中的opt/modules/zookeeper-3.4.9/dataDir/myid文件中的值为2。

修改centos03节点中的opt/modules/zookeeper-3.4.9/dataDir/myid文件中的值为3。

5.启动ZooKeeper

分别进入每个节点的ZooKeeper安装目录,执行如下命令:

bin/zkServer.sh start

输出以下信息代表启动成功:

ZooKeeper JMX enabled by default

Using config: /usr/local/zookeeper-3.4.9/bin/../conf/zoo.cfg

Starting zookeeper ... STARTED

需要注意的是,每台服务器都要执行一遍启动命令,这样才能使得整个集群启动起来。

6.查看启动状态

分别在各个节点上执行如下命令,查看ZooKeeper服务的状态:

bin/zkServer.sh status

在centos01节点上查看服务状态,输出了以下信息:

ZooKeeper JMX enabled by default

Using config: /usr/local/zookeeper-3.4.9/bin/../conf/zoo.cfg

Mode: follower

在centos02服务器上查看服务状态,输出了以下信息:

ZooKeeper JMX enabled by default

Using config: /usr/local/zookeeper-3.4.9/bin/../conf/zoo.cfg

Mode: follower

在centos03服务器上查看服务状态,输出了以下信息:

ZooKeeper JMX enabled by default

Using config: /usr/local/zookeeper-3.4.9/bin/../conf/zoo.cfg

Mode: leader

由此可见,本例中centos03服务器上的ZooKeeper服务为Leader,其余两个ZooKeeper服务为Follower。

如果在查看启动状态时输出以下信息,说明ZooKeeper集群启动不成功,出现错误。

Error contacting service. It is probably not running.

此时需要修改bin/zkEvn.sh文件中的以下内容,将错误信息输出到日志文件。

if [ "x${ZOO_LOG4J_PROP}" = "x" ]
then
ZOO_LOG4J_PROP="INFO,CONSOLE"
fi

将上述内容中的CONSOLE改为ROLLINGFILE,修改后的内容如下:

if [ "x${ZOO_LOG4J_PROP}" = "x" ]
then
ZOO_LOG4J_PROP="INFO,ROLLINGFILE"
fi

修改后,重新启动ZooKeeper集群,查看在ZooKeeper安装目录下生成的日志文件zookeeper.log,发现报以下错误:

java.net.NoRouteToHostException: 没有到主机的路由。

产生上述错误的原因是,系统没有关闭防火墙,导致ZooKeeper集群间连接不成功。因此需要关闭系统防火墙(为了防止出错,在最初的集群环境配置的时候可以直接将防火墙关闭),CentOS7关闭防火墙的命令如下:

systemctl stop firewalld.service
systemctl disable firewalld.service

关闭各节点的防火墙后,重新启动ZooKeeper,再一次查看启动状态,发现一切正常了。

7.测试客户端连接

在centos01节点上(其它节点也可以),进入ZooKeeper安装目录,执行以下命令,可以连接ZooKeeper服务器,连接成功后可以输入ZooKeeper的Shell命令进行操作与测试了。

[hadoop@centos01]$ bin/zkCli.sh -server centos01:2181

8.2 命令行操作

【操作目的】

ZooKeeper的命令行工具类似于Shell。当ZooKeeper服务启动以后,可以在其中一台运行ZooKeeper服务的服务器中输入以下命令(需要进入ZooKeeper安装目录),启动一个客户端,连接到ZooKeeper集群:

[hadoop@centos01]$ bin/zkCli.sh -server centos01:2181

连接成功后,系统会输出ZooKeeper的运行环境及配置信息,并在屏幕输出“Welcome to ZooKeeper”等欢迎信息。之后就可以使用ZooKeeper命令行工具了。

【操作步骤】

以下是ZooKeeper命令行工具的一些简单操作示例:

(1)使用ls命令,可以查看当前ZooKeeper中所包含的内容:

[zk: centos01:2181(CONNECTED) 4] ls /
[zookeeper]

可以看到,当前有一个名称为zookeeper的Znode节点。

(2)使用create命令,可以创建一个新的Znode节点。例如,创建一个名为“zk”的Znode以及在它上面存放的元数据字符串“myData”,命令及输出信息如下:

[zk: centos01:2181(CONNECTED) 2] create /zk "myData"
Created /zk

(3)使用get命令,可以查看某个Znode的详细信息及其包含的元数据字符串。例如,查看Znode节点/zk的详细信息,命令及输出信息如下:

[zk: centos01:2181(CONNECTED) 6] get /zk
myData
cZxid = 0x800000002
ctime = Thu Mar 22 10:12:11 CST 2018
mZxid = 0x800000002
mtime = Thu Mar 22 10:12:11 CST 2018
pZxid = 0x800000002
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 6
numChildren = 0

(4)使用set命令,可以修改Znode节点的元数据字符串。例如,将Znode节点/zk所关联的字符串修改为“myDataUpdate”,命令及输出信息如下:

[zk: centos01:2181(CONNECTED) 10] set /zk "myDataUpdate"
cZxid = 0x800000002
ctime = Thu Mar 22 10:12:11 CST 2018
mZxid = 0x800000005
mtime = Thu Mar 22 10:18:19 CST 2018
pZxid = 0x800000002
cversion = 0
dataVersion = 3
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 12
numChildren = 0

(5)使用delete命令,可以将某个Znode节点删除。例如,删除上面创建的Znode节点/zk,命令如下:

[zk: centos01:2181(CONNECTED) 11] delete /zk

使用ZooKeeper命令行工具也可以创建有层次的目录。例如,在/zk节点目录下创建新的目录node1,并关联其元数据为“nodeData”,命令及输出信息如下:

[zk: centos01:2181(CONNECTED) 18] create /zk/node1 "nodeData"
Created /zk/node1

8.3 Java API操作

除了可以使用命令行方式对ZooKeeper进行操作外,ZooKeeper还提供了Java API操作接口。下面对ZooKeeper的常用Java API接口进行介绍。

8.3.1 创建Java工程

在编写Java API之前,首先需要新建一个ZooKeeper项目。ZooKeeper项目的结构与普通的Java项目一样,只是依赖的jar包不同。

在eclipse中新建一个Maven项目zk_demo(Maven项目的搭建此处不做过多讲解),然后在该项目的pom.xml文件中添加以下代码,以引入ZooKeeper的Java API依赖包:

   <dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.9</version>
</dependency>

配置好pom.xml后,即可进行ZooKeeper Java API的编写。

8.3.2 创建节点

Zookeeper创建节点不支持递归调用,即无法在父节点不存在的情况下创建一个子节点,如在/zk0l节点不存在的情况下创建/zk01/ch01节点;并且如果一个节点已经存在,那么创建同名节点时,会抛出NodeExistsException异常。

下面我们创建一个节点/ zk001,节点的元数据为“zk001_data”,步骤如下:

1.编写代码

在新建的zk_demo项目中新建Java类CreatePath.java,完整代码如下所示:

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.ZooDefs.Ids; public class CreatePath { public static void main(String[] args) throws Exception {
String connectStr="192.168.170.128:2181,192.168.170.129:2181,192.168.170.130:2181";
//参数1:服务器连接字符串
//参数2:连接超时时间
//参数3:观察者对象(回调函数)
ZooKeeper zk = new ZooKeeper(connectStr, 3000, null);
/* 1.CreateMode 取值
* PERSISTENT:持久化节点
* PERSISTENT_SEQUENTIAL:顺序自动编号的目录节点
* EPHEMERAL:临时目录节点,客户端断开连接时,这种节点会被自动删除
* EPHEMERAL_SEQUENTIAL:临时自动编号节点
* */
String path=zk.create("/zk001", "zk001_data".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
System.out.println(path);
}
}

2.程序解读

ZooKeeper zk  = new ZooKeeper(connectStr, 3000, null);

新建一个ZooKeeper对象,传入三个参数,第一个参数为以逗号分隔的服务器连接字符串,格式:“host:端口”,这里需要把所有的ZooKeeper服务器的地址都写上,而不是只写其中一台。ZooKeeper客户端对象将从连接串中挑选任意一个服务器进行连接,如果连接失败,将尝试连接另外一个服务器,直到建立连接。这样的好处是能保证ZooKeeper服务的高可靠性,防止因为其中一台机器宕机而导致连接失败。第二个参数为连接超时时间,这里是3秒。第三个参数为观察者对象,连接成功后会调用观察者对象中的回调函数,这里传入null即可。

String path=zk.create("/zk001", "zk001_data".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);

调用ZooKeeper对象的创建节点函数,返回创建的节点路径,并需要传入四个参数。第一个参数为节点名称。第二个参数为节点数据,需要转成字节数组。第三个参数为权限控制,这里使用ZooKeeper自带的完全开放权限Ids.OPEN_ACL_UNSAFE。第四个参数为创建模式,它是一个枚举类型,共有四个取值,PERSISTENT(持久化,这个目录节点存储的数据不会丢失 ,即客户端失去连接之后不会被自动删除)、PERSISTENT_SEQUENTIAL(顺序自动编号的目录节点,这种目录节点在命名上会根据当前已经存在的节点数自动加 1,然后将已经成功创建的目录节点名返回给客户端)、EPHEMERAL(临时目录节点,客户端断开连接时,这种节点会被自动删除)、EPHEMERAL_SEQUENTIAL(临时自动编号目录节点,客户端断开连接时,这种节点也会被自动删除)。

3.运行程序

直接在eclipse中右击运行该程序即可。

8.3.3 添加数据

我们可以通过调用ZooKeeper对象的setData()函数给节点添加数据,示例代码如下:

@Test
public void setNodeData() throws Exception {
String connectStr="192.168.170.128:2181,192.168.170.129:2181,192.168.170.130:2181";
ZooKeeper zk = new ZooKeeper(connectStr, 3000, null);
Stat stat = zk.setData("/zk002", "zk002_data2".getBytes(), -1);
System.out.println(stat.getVersion());
}

代码解析:

Stat stat = zk.setData("/zk002", "zk002_data2".getBytes(), -1);

setData函数的第一个参数为节点路径。第二个参数为需要添加的数据,并转成字节数组。第三个参数为版本号,-1代表所有版本。

8.3.4 获取数据

我们可以调用ZooKeeper对象的getData()函数,获得指定节点的数据,示例代码如下:

@Test
public void getNodeData() throws Exception {
String connectStr="192.168.170.128:2181,192.168.170.129:2181,192.168.170.130:2181";
ZooKeeper zk = new ZooKeeper(connectStr, 3000, null);
Stat stat=new Stat();
//返回指定路径上的节点数据和节点状态,节点的状态会放入stat对象中
byte[] bytes=zk.getData("/zk002", null, stat);
System.out.println(new String(bytes));
}

上述代码获取了节点/zk002的数据,而且转成了字符串进行了输出,并将节点/zk002的状态放入了对象stat中。如需查看状态信息,可以从对象stat中进行输出查看。

可以看到,在getData函数的第二个参数,传入的是null,也可以指定一个观察者对象watcher,对节点数据的变化进行监听,一旦有数据改变,就会触发watcher指定的回调函数。我们对上方代码加入观察者后,示例代码如下:

@Test
public void getNodeDataWatch() throws Exception {
String connectStr="192.168.170.128:2181,192.168.170.129:2181,192.168.170.130:2181";
ZooKeeper zk = new ZooKeeper(connectStr, 3000, null);
Stat stat=new Stat();
//返回指定路径上的节点数据和节点状态,节点的状态会放入stat对象中
byte[] bytes=zk.getData("/zk002", new Watcher(){
@Override
public void process(WatchedEvent event) {
System.out.println(event.getType());
} }, stat);
System.out.println(new String(bytes)); //改变节点数据,触发watch
zk.setData("/zk002", "zk002_data_testwatch".getBytes(), -1); //为了验证是否触发了watch,不让程序结束
while(true){
Thread.sleep(3000);
} }

代码分析:

public void process(WatchedEvent event) {
System.out.println(event.getType());
}

process 方法是 Watcher 接口中的一个回调方法,当 ZooKeeper 向客户端发送一个 Watcher 事件通知时,客户端就会对相应的 process 方法进行回调,从而实现对事件的处理。

process 方法包含 WatcherEvent 类型的参数,WatchedEvent 包含了每一个事件的三个基本属性:通知状态(KeeperState)、事件类型(EventType)和节点路径(Path),ZooKeeper 使用 WatchedEvent 对象来封装服务端事件并传递给 Watcher,从而方便回调方法 process 对服务端事件进行处理。

上述代码通过System.out.println(event.getType());输出服务端的事件类型,输出结果为NodeDataChanged。从结果单词的含义可知,节点数据被改变了。

while(true){
Thread.sleep(3000);
}

为了能够更好的验证是否触发了watch,不让程序一次执行到底,从而加入了上方代码,让程序一直停留在此处。

8.3.5 删除节点

我们可以通过调用ZooKeeper对象的delete()函数,对指定路径节点进行删除。示例代码如下:

@Test
public void deletePath() throws Exception{
String connectStr="192.168.170.128:2181,192.168.170.129:2181,192.168.170.130:2181";
ZooKeeper zk = new ZooKeeper(connectStr, 3000, null);
//删除节点
zk.delete("/zk001", -1);
}

上述代码中,delete函数需要传入两个参数,第一个参数为需要删除的节点路径。第二个参数为节点版本,如果是-1则代表删除所有版本。

原创文章,转载请注明出处!!

第8章 ZooKeeper操作的更多相关文章

  1. 学习Zookeeper之第3章Zookeeper内部原理

    第 3 章 Zookeeper 内部原理 3.1 选举机制 3.2 节点类型 3.3 stat 结构体 3.4 监听器原理   1)监听原理详解   2)常见的监听 3.5 写数据流程 第 3 章 Z ...

  2. 学习Zookeeper之第2章Zookeeper安装

    第 2 章 Zookeeper安装 2.1 本地模式安装部署 2.2 配置参数解读 第 2 章 Zookeeper安装 2.1 本地模式安装部署 1)安装前准备: (1)安装 jdk (2)通过 fi ...

  3. Zookeeper操作

    Zookeeper操作 注意搭建: 1.集群规模不小于3个节点 2.服务器之间系统时间要保持一致 1.搭建步骤: 1.解压安装包 2.设置zookeeper环境变量 3.修改配置文件————zoo.c ...

  4. 第四章 JavaScript操作DOM对象

    第四章   JavaScript操作DOM对象 一.DOM操作 DOM是Document Object Model的缩写,即文档对象模型,是基于文档编程的一套API接口,1988年,W3C发布了第一级 ...

  5. 第三章 JavaScript操作BOM对象

    第三章   JavaScript操作BOM对象 一.window对象 浏览器对象模型(BOM)是javascript的组成之一,它提供了独立与浏览器窗口进行交换的对象,使用浏览器对象模型可以实现与HT ...

  6. 学习Zookeeper之第1章Zookeeper入门

    第 1 章 Zookeeper入门 1.1 概述 1.2 特点 1.3 数据结构 1.4 应用场景 统一命名服务 统一配置管理 统一集群管理 服务器动态上下线 软负载均衡 1.5 下载地址 第 1 章 ...

  7. 第3章 ZooKeeper基本数据模型

    第3章 ZooKeeper基本数据模型 3-1 zk数据模型介绍 3-2 zk客户端连接关闭服务端,查看znode ./zkCli.sh Ctrl + C 退出 =================== ...

  8. 第2章 ZooKeeper安装与启动

    第2章 ZooKeeper安装 2-1 JDK的安装 需要先在Linux系统下安装JDK1.8 tar -zxvf jdk-8u231-linux-x64.tar.gz rm -f jdk-8u231 ...

  9. 第一章 zookeeper基础概念

    1.ZooKeeper是什么 ZooKeeper为分布式应用提供了高效且可靠的分布式协调服务,提供了统一命名服务. 配置管理和分布式锁等分布式的基础服务.在解决分布式数据一致性方面, ZooKeepe ...

随机推荐

  1. 密码存储中MD5的安全问题与替代方案

    md5安全吗?有多么地不安全?如何才能安全地存储密码?... md5安全吗? 经过各种安全事件后,很多系统在存放密码的时候不会直接存放明文密码了,大都改成了存放了 md5 加密(hash)后的密码,可 ...

  2. C++ Notes 1 - size_type - Accelerated Ch3

    1. 为什么用string::size_type而不是int? --Why use string::size_type ? int is supposed to work! it holds numb ...

  3. fork: retry: Resource temporarily unavailable

    用户A打开文件描述符太多,超过了该用户的限制 修改用户可以打开的文件描述符数量 1.首先,用另一个用户B登录,修改/etc/security/limit.conf * soft nofile 6553 ...

  4. Spark资源调度分配内幕天机彻底解密:Driver在Cluster模式下的启动、两种不同的资源调度方式源码彻底解析、资源调度内幕总结

    本课主题 Master 资源调度的源码鉴赏 资源调度管理 任务调度与资源是通过 DAGScheduler.TaskScheduler.SchedulerBackend 等进行的作业调度 资源调度是指应 ...

  5. GO语言(四)线程通信

    package main import "fmt" func fibon(c,quit chan int) { x,y := , for { select { case c < ...

  6. bzoj1434 [ZJOI2009]染色游戏

    Description 一共n × m 个硬币,摆成n × m 的长方形.dongdong 和xixi 玩一个游戏, 每次可以选择一个连通块,并把其中的硬币全部翻转,但是需要满足存在一个 硬币属于这个 ...

  7. php无极限分类函数

    /** * [make_tree description] * @Author Lerko * @DateTime 2017-04-01T14:57:24+0800 * @param [type] $ ...

  8. ssm小小整合

    ssm整合: 首先是创建数据库: CREATE TABLE `user` ( `id` ) NOT NULL, `username` varchar() NOT NULL, `password` va ...

  9. Linux Shell 编程 文件转置问题

    给定一个文件 file.txt,转置它的内容. 你可以假设每行列数相同,并且每个字段由 ' ' 分隔. 示例: 假设 file.txt 文件内容如下: name age alice 21 ryan 3 ...

  10. vue中调用地图

    一. vue-amap,一个基于 Vue 2.x 和高德地图的地图组件 这个就不细说了,按照其文档,就能够安装下来. 二. 按照官方提供的方法引入 1.修改webpac.base.conf.js文件 ...