本节内容:
-
Zookeeper介绍
-
Zookeeper特点
-
Zookeeper应用场景
-
用到了Zookeeper的一些系统
-
Zookeeper集群安装部署
一、Zookeeper介绍
-
是一个针对大型分布式系统的可靠协调系统;
-
提供的功能包括:配置维护、名字服务、分布式同步、组服务等;
-
目标就是封装好复杂易出错的关键职务,将简单易用的接口和性能高效、功能稳定的系统提供给用户;
-
Zookeeper已经成为Hadoop生态系统中的基础组件。
二、Zookeeper特点
-
最终一致性:为客户端展示同一视图,这是Zookeeper最重要的性能;
-
可靠性:如果消息被一台服务器接受,那么它将被所有的服务器接受;
-
原子性:更新只能成功或失败,没有中间状态;
三、Zookeeper应用场景
1. 统一命名服务
(1)分布式环境下,经常需要对应用/服务进行统一命名,便于识别不同的服务
-
类似于域名与ip之间对应关系,域名容易记住;
-
通过名称来获取资源或服务的地址,提供者信息。
(2)按照层次结构组织服务/应用名称
-
可将服务名称以及地址信息写在Zookeeper上,客户端通过Zookeeper获取可用服务列表。
2. 配置管理
(1)分布式环境下,配置文件管理和同步是一个常见问题
-
一个集群中,所有节点的配置信息是一致的,比如Hadoop;
-
对配置文件修改后,希望能够快速同步到各个节点上。
(2)配置管理可交由Zookeeper实现
-
可将配置信息写入Zookeeper的一个znode上;
-
各个节点监听这个znode
-
一旦znode中的数据被修改,Zookeeper将会通知各个节点。
3. 集群管理
(1)分布式环境下,实时掌握每个节点的状态是必要的
(2)可交由Zookeeper实现
-
可将节点信息写入Zookeeper的一个znode上;
-
监听这个znode可获得它的实时状态变化。
(3)典型应用
4. 分布式通知/协调
原理其实就是发布/订阅。
(1)分布式环境下经常存在一个服务需要知道它所管理的子服务的状态
(2)心跳检测机制可通过Zookeeper实现
(3)信息推送可由Zookeeper实现(发布/订阅模式)
5. 分布式锁
(1)Zookeeper是强一致性的
-
多个客户端同时在Zookeeper上创建相同znode,只有一个创建成功。
(2)实现锁的独占性
-
多个客户端同时在Zookeeper上创建相同znode,创建成功的那个客户端得到锁,其他客户端等待。
(3)控制锁的时序
-
各个客户端在某个znode下创建临时znode(类型为CreateMode.EPHEMERAL_SEQUENTIAL),这样,该znode可掌握全局访问时序。
四、用到了Zookeeper的一些系统
-
HDFS
-
YARN
-
Storm
-
HBase
-
Flume
-
Dubbo
-
metaq
五、Zookeeper集群安装部署
下面开始介绍Zookeeper的安装部署。安装部署分三种模式:单机模式、伪分布式模式和分布式模式。单机模式和伪分布式比较简单,多用于本地测试调试,下面介绍分布式模式安装部署。
注意:3台机器都需要安装zk。对于Zookeeper集群的话,官方推荐的最小节点数为3个。
1. 环境信息
主机名
|
操作系统版本
|
IP地址
|
安装软件
|
console
|
CentOS 7.0
|
114.55.29.246
|
JDK1.7、zookeeper-3.4.6
|
log1
|
CentOS 7.0
|
114.55.29.86
|
JDK1.7、zookeeper-3.4.6
|
log2
|
CentOS 7.0
|
114.55.29.241
|
JDK1.7、zookeeper-3.4.6
|
2. 安装jdk1.7
3台机器都需要安装jdk1.7
[root@log1 local]# mkdir /usr/java
[root@log1 local]# tar zxf jdk-7u80-linux-x64.gz -C /usr/java/
[root@log1 local]#
vim /etc/profile
export JAVA_HOME=/usr/java/jdk1.7.0_80
export PATH=$JAVA_HOME/bin:$PATH
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
[root@log1 local]#
source /etc/profile
3. 安装配置zk
(1)配置zk节点的hosts文件:配置3台机器的ip地址和主机名的对应关系。以下以console主机为例,
其hosts文件添加下面3行:
114.55.29.246 console
114.55.29.86 log1
114.55.29.241 log2
(2)解压安装配置第一台zk
[root@console local]# tar zxf zookeeper-3.4.6.tar.gz
[root@console local]# cd zookeeper-3.4.6
创建
快照日志存放目录:
[root@console zookeeper-3.4.6]# mkdir -p dataDir
创建
事务日志存放目录:
[root@console zookeeper-3.4.6]# mkdir dataLogDir
【注意】:如果不配置dataLogDir,那么事务日志也会写在dataDir目录中。这样会严重影响zk的性能。因为在zk吞吐量很高的时候,产生的事务日志和快照日志太多。
修改配置文件,添加如下内容:
[root@console zookeeper-3.4.6]# cd conf
[root@console conf]# mv zoo_sample.cfg zoo.cfg
[root@console conf]# vim zoo.cfg
# 存放数据文件
dataDir=/usr/local/zookeeper-3.4.6/dataDir
# 存放日志文件
dataLogDir=/usr/local/zookeeper-3.4.6/dataLogDir
# zookeeper cluster,2888为选举端口,3888为心跳端口
server.1=console:2888:3888
server.2=log1:2888:3888
server.3=log2:2888:3888
在我们配置的dataDir指定的目录下面,创建一个myid文件,
里面内容为一个数字,用来标识当前主机,
conf/zoo.cfg文件中配置的server.X中X为什么数字,则myid文件中就输入这个数字:
[root@console ~]#
echo "1" > /usr/local/zookeeper-3.4.6/dataDir/myid
(3)远程复制第一台的zk到另外两台上,并修改myid文件为2和3
[root@console local]# scp -rp zookeeper-3.4.6 root@114.55.29.86:/usr/local/
[root@console local]# scp -rp zookeeper-3.4.6 root@114.55.29.241:/usr/local/
4. 启动和关闭zk
在ZooKeeper集群的每个结点上,执行启动ZooKeeper服务的脚本,如下所示:
[root@console bin]# ./zkServer.sh start
[root@log1 bin]# ./zkServer.sh start
[root@log2 bin]# ./zkServer.sh start
日志可查询:/usr/local/zookeeper-3.4.6/bin/zookeeper.out
可以通过命令jps查看Zookeeper进程:
停止zk命令:
# /usr/local/zookeeper-3.4.6/bin/zkServer.sh stop
5. 测试zk集群
可以通过ZooKeeper的脚本来查看启动状态,包括集群中各个结点的角色(或是Leader,或是Follower)
[root@console bin]#
./zkServer.sh status
JMX enabled by default
Using config: /usr/local/zookeeper-3.4.6/bin/../conf/zoo.cfg
Mode: follower
[root@log1 bin]#
./zkServer.sh status
JMX enabled by default
Using config: /usr/local/zookeeper-3.4.6/bin/../conf/zoo.cfg
Mode: leader
[root@log2 bin]#
./zkServer.sh status
JMX enabled by default
Using config: /usr/local/zookeeper-3.4.6/bin/../conf/zoo.cfg
Mode: follower
通过上面状态查询结果可见,log1是集群的Leader,其余的两个结点是Follower。
另外,可以通过客户端脚本,连接到ZooKeeper集群上。对于客户端来说,ZooKeeper是一个整体,连接到ZooKeeper集群实际上感觉在独享整个集群的服务,所以,你可以在任何一个结点上建立到服务集群的连接。
[root@log2 bin]#
./zkCli.sh -server log1:2181
Connecting to log1:2181
2016-03-08 14:21:31,502 [myid:] - INFO [main:Environment@100] - Client environment:zookeeper.version=3.4.6-1569965, built on 02/20/2014 09:09 GMT
2016-03-08 14:21:31,505 [myid:] - INFO [main:Environment@100] - Client environment:host.name=log2
2016-03-08 14:21:31,505 [myid:] - INFO [main:Environment@100] - Client environment:java.version=1.7.0_80
2016-03-08 14:21:31,507 [myid:] - INFO [main:Environment@100] - Client environment:java.vendor=Oracle Corporation
2016-03-08 14:21:31,507 [myid:] - INFO [main:Environment@100] - Client environment:java.home=/usr/java/jdk1.7.0_80/jre
2016-03-08 14:21:31,507 [myid:] - INFO [main:Environment@100] - Client environment:java.class.path=/usr/local/zookeeper-3.4.6/bin/../build/classes:/usr/local/zookeeper-3.4.6/bin/../build/lib/*.jar:/usr/local/zookeeper-3.4.6/bin/../lib/slf4j-log4j12-1.6.1.jar:/usr/local/zookeeper-3.4.6/bin/../lib/slf4j-api-1.6.1.jar:/usr/local/zookeeper-3.4.6/bin/../lib/netty-3.7.0.Final.jar:/usr/local/zookeeper-3.4.6/bin/../lib/log4j-1.2.16.jar:/usr/local/zookeeper-3.4.6/bin/../lib/jline-0.9.94.jar:/usr/local/zookeeper-3.4.6/bin/../zookeeper-3.4.6.jar:/usr/local/zookeeper-3.4.6/bin/../src/java/lib/*.jar:/usr/local/zookeeper-3.4.6/bin/../conf:.:/usr/java/jdk1.7.0_80/lib/dt.jar:/usr/java/jdk1.7.0_80/lib/tools.jar
2016-03-08 14:21:31,507 [myid:] - INFO [main:Environment@100] - Client environment:java.library.path=/usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
2016-03-08 14:21:31,508 [myid:] - INFO [main:Environment@100] - Client environment:java.io.tmpdir=/tmp
2016-03-08 14:21:31,508 [myid:] - INFO [main:Environment@100] - Client environment:java.compiler=
2016-03-08 14:21:31,508 [myid:] - INFO [main:Environment@100] - Client environment:os.name=Linux
2016-03-08 14:21:31,508 [myid:] - INFO [main:Environment@100] - Client environment:os.arch=amd64
2016-03-08 14:21:31,508 [myid:] - INFO [main:Environment@100] - Client environment:os.version=3.10.0-123.9.3.el7.x86_64
2016-03-08 14:21:31,508 [myid:] - INFO [main:Environment@100] - Client environment:user.name=root
2016-03-08 14:21:31,508 [myid:] - INFO [main:Environment@100] - Client environment:user.home=/root
2016-03-08 14:21:31,508 [myid:] - INFO [main:Environment@100] - Client environment:user.dir=/usr/local/zookeeper-3.4.6/bin
2016-03-08 14:21:31,510 [myid:] - INFO [main:ZooKeeper@438] - Initiating client connection, connectString=log1:2181 sessionTimeout=30000 watcher=org.apache.zookeeper.ZooKeeperMain$MyWatcher@ee01430
Welcome to ZooKeeper!
2016-03-08 14:21:31,534 [myid:] - INFO [main-SendThread(log1:2181):ClientCnxn$SendThread@975] - Opening socket connection to server log1/114.55.29.86:2181. Will not attempt to authenticate using SASL (unknown error)
2016-03-08 14:21:31,539 [myid:] - INFO [main-SendThread(log1:2181):ClientCnxn$SendThread@852] - Socket connection established to log1/114.55.29.86:2181, initiating session
JLine support is enabled
[zk: log1:2181(CONNECTING) 0] 2016-03-08 14:21:31,572 [myid:] - INFO [main-SendThread(log1:2181):ClientCnxn$SendThread@1235] - Session establishment complete on server log1/114.55.29.86:2181, sessionid = 0x25354db0d430000, negotiated timeout = 30000
WATCHER::
WatchedEvent state:SyncConnected type:None path:null
[zk: log1:2181(CONNECTED) 0]
6. 脚本定期清理zk快照和日志文件
正常运行过程中,ZK会不断地把快照数据和事务日志输出到dataDir和dataLogDir这两个目录,并且如果没有人为操作的话,ZK自己是不会清理这些文件的。 我这里采用脚本切割。
[root@log1 ~]# cd /usr/local/zookeeper-3.4.6/
[root@log1 zookeeper-3.4.6]# vim clean_zklog.sh
#!/bin/bash
# Snapshot file dir.
dataDir=/usr/local/zookeeper-3.4.6/dataDir/version-2
# Transaction logs dir.
dataLogDir=/usr/local/zookeeper-3.4.6/dataLogDir/version-2
# Reserved 5 files.
COUNT=5
ls -t $dataDir/snapshot.* | tail -n +$[$COUNT+1] | xargs rm -f
ls -t $dataLogDir/log.* | tail -n +$[$COUNT+1] | xargs rm -f
[root@log1 zookeeper-3.4.6]# chmod +x clean_zklog.sh
每个Zookeeper集群节点配置周期性任务,每个星期日的0点0分执行:
[root@console zookeeper-3.4.6]# crontab -e
0 0 * * 0 /usr/local/zookeeper-3.4.6/clean_zklog.sh
zookeeper有单机、伪集群、集群三种部署方式,可根据自己对可靠性的需求选择合适的部署方式。下边对这三种部署方式逐一进行讲解。
一、单机安装
1.1 下载
进入要下载的版本的目录,选择.tar.gz文件下载
下载链接:
1.2 安装
使用tar解压要安装的目录即可,以3.4.5版本为例
这里以解压到/usr/myapp,实际安装根据自己的想安装的目录修改(注意如果修改,那后边的命令和配置文件中的路径都要相应修改)
tar -zxf zookeeper-3.4.5.tar.gz -C /usr/myapp
1.3 配置
在主目录下创建data和logs两个目录用于存储数据和日志:
cd /usr/myapp/zookeeper-3.4.5
mkdir data
mkdir logs
在conf目录下新建zoo.cfg文件,写入以下内容保存:
tickTime=2000
dataDir=/usr/myapp/zookeeper-3.4.5/data
dataLogDir=/usr/myapp/zookeeper-3.4.5/logs
clientPort=2181
1.4 启动和停止
进入bin目录,启动、停止、重启分和查看当前节点状态(包括集群中是何角色)别执行:
./zkServer.sh start
./zkServer.sh stop
./zkServer.sh restart
./zkServer.sh status
二、伪集群模式
伪集群模式就是在同一主机启动多个zookeeper并组成集群,下边以在192.168.220.128主机上创3个zookeeper组集群为例。
将通过第一大点安装的zookeeper,复制成zookeeper1/zookeeper2/zookeeper3三份
2.1 zookeeper1配置
zookeeper1配置文件conf/zoo.cfg修改如下:
tickTime=2000
dataDir=/usr/myapp/zookeeper1/data
dataLogDir=/usr/myapp/zookeeper1/logs
clientPort=2181
initLimit=5
syncLimit=2
server.1=192.168.220.128:2888:3888
server.2=192.168.220.128:4888:5888
server.3=192.168.220.128:6888:7888
zookeeper1的data/myid配置如下:
echo '1' > data/myid
2.2 zookeeper2配置
zookeeper2配置文件conf/zoo.cfg修改如下:
tickTime=2000
dataDir=/usr/myapp/zookeeper2/data
dataLogDir=/usr/myapp/zookeeper2/logs
clientPort=3181
initLimit=5
syncLimit=2
server.1=192.168.220.128:2888:3888
server.2=192.168.220.128:4888:5888
server.3=192.168.220.128:6888:7888
zookeeper2的data/myid配置如下:
echo '2' > data/myid
2.3 zookeeper3配置
zookeeper3配置文件conf/zoo.cfg修改如下:
tickTime=2000
dataDir=/usr/myapp/zookeeper3/data
dataLogDir=/usr/myapp/zookeeper3/logs
clientPort=4181
initLimit=5
syncLimit=2
server.1=192.168.220.128:2888:3888
server.2=192.168.220.128:4888:5888
server.3=192.168.220.128:6888:7888
zookeeper3的data/myid配置如下:
echo '3' > data/myid
最后使用1.4的命令把三个zookeeper都启动即可,启动顺序随意没要求。
三、集群模式
集群模式就是在不同主机上安装zookeeper然后组成集群的模式;下边以在
192.168.220.128/129/130三台主机为例。
将第1.1到1.3步中安装好的zookeeper打包复制到129和130上,并都解压到同样的目录下。
3.1 conf/zoo.cfg文件修改
三个zookeeper的conf/zoo.cfg修改如下:
tickTime=2000
dataDir=/usr/myapp/zookeeper-3.4.5/data
dataLogDir=/usr/myapp/zookeeper-3.4.5/logs
clientPort=2181
initLimit=5
syncLimit=2
server.1=192.168.220.128:2888:3888
server.2=192.168.220.129:2888:3888
server.3=192.168.220.130:2888:3888
对于129和130,由于安装目录都是zookeeper-3.4.5所以dataDir和dataLogDir不需要改变,又由于在不同机器上所以clientPort也不需要改变
所以此时129和130的conf/zoo.cfg的内容与128一样即可。
3.2 data/myid文件修改
128 data/myid修改如下:
echo '1' > data/myid
129 data/myid修改如下:
echo '2' > data/myid
130 data/myid修改如下:
echo '3' > data/myid
最后使用1.4的命令把三个zookeeper都启动即可,启动顺序随意没要求。
四、报错及处理
应用连接zookeepr报错:Session 0x0 for server 192.168.220.128/192.168.220.128:2181,unexpected error,closing socket connection and attempting reconnect;
先看端口能否telnet通,如果通则使用./zkServer.sh status查看zk是否确实已启动,没启查看bin/zookeeper.out中的报错。
bin/zookeeper.out中报错:“zookeeper address already in use”;显然端口被占用,要么是其他进程占用了配置的端口,要么是上边配置的clientPort和server中的端口有重复。
bin/zookeeper.out中报错:Cannot open channel to 2 at election address /192.168.220.130:3888;这应该只是组成集群的130节点未启动,到130启动起来zk即会正常。
Zookeeper安装
zookeeper的安装分为三种模式:单机模式、集群模式和伪集群模式。
单机模式
首先,从Apache官网下载一个Zookeeper稳定版本,本次教程采用的是zookeeper-3.4.9版本。
然后解压zookeeper-3.4.9.tar.gz文件到安装目录下:
tar -zxvf zookeepre-3.4.9.tar.gz
zookeeper要求Java运行环境,并且需要jdk版本1.6以上。为了以后的操作方便,可以对zookeeper的环境变量进行配置(该步骤可忽略)。方法如下,在/etc/profile文件中加入以下内容:
#Set Zookeeper Environment
export ZOOKEEPER_HOME=/root/zookeeper-3.4.9
export PATH=$ZOOKEEPER_HOME/bin;$ZOOKEEPER_HOME/conf
Zookeeper服务器包含在单个jar文件中(本环境下为 zookeeper-3.4.9.jar),安装此服务需要用户自己创建一个配置文件。
默认配置文件路径为 Zookeeper-3.4.9/conf/目录下,文件名为zoo.cfg。进入conf/目录下可以看到一个zoo_sample.cfg文件,可供参考。通过以下代码在conf目录下创建zoo.cfg文件:
gedit zoo.cfg
在文件中输入以下内容并保存
tickTime=2000
dataDir=/home/jxwch/hadoop/data/zookeeper
dataLogDir=/home/jxwch/hadoop/dataLog/zookeeper
clientPort=2181
在这个文件中,各个语句的含义:
tickTime : 服务器与客户端之间交互的基本时间单元(ms)
dataDir : 保存zookeeper数据路径
dataLogDir : 保存zookeeper日志路径,当此配置不存在时默认路径与dataDir一致
clientPort : 客户端访问zookeeper时经过服务器端时的端口号
使用单机模式时需要注意,在这种配置方式下,如果zookeeper服务器出现故障,zookeeper服务将会停止。
集群模式
zookeeper最主要的应用场景是集群,下面介绍如何在一个集群上部署一个zookeeper。只要集群上的大多数zookeeper服务启动了,那么总的zookeeper服务便是可用的。
另外,最好使用奇数台服务器。
如歌zookeeper拥有5台服务器,那么在最多2台服务器出现故障后,整个服务还可以正常使用。
之后的操作和单机模式的安装类似,我们同样需要Java环境,下载最新版的zookeeper并配置相应的环境变量。不同之处在于每台机器上的conf/zoo.cfg配置文件的参数设置不同,用户可以参考下面的配置:
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/home/jxwch/server1/data
dataLogDir=/home/jxwch/server1/dataLog
clientPort=2181
server.1=zoo1:2888:3888
server.2=zoo2:2888:3888
server.3=zoo3:2888:3888
maxClientCnxns=60
在这个配置文件中,新出现的语句的含义:
initLimit : 此配置表示允许follower连接并同步到leader的初始化时间,它以tickTime的倍数来表示。当超过设置倍数的tickTime时间,则连接失败。
syncLimit : Leader服务器与follower服务器之间信息同步允许的最大时间间隔,如果超过此间隔,默认follower服务器与leader服务器之间断开链接。
maxClientCnxns : 限制连接到zookeeper服务器客户端的数量
server.id=host:port:port : 表示了不同的zookeeper服务器的自身标识,作为集群的一部分,每一台服务器应该知道其他服务器的信息。用户可以从“server.id=host:port:port” 中读取到相关信息。
在服务器的data(dataDir参数所指定的目录)下创建一个文件名为myid的文件,这个文件的内容只有一行,指定的是自身的id值。
比如,服务器“1”应该在myid文件中写入“1”。这个id必须在集群环境中服务器标识中是唯一的,且大小在1~255之间。
这一样配置中,zoo1代表第一台服务器的IP地址。
第一个端口号(port)是从follower连接到leader机器的端口,
第二个端口是用来进行leader选举时所用的端口。
在集群配置过程中有三个非常重要的端口:clientPort:2181、port:2888、port:3888。
伪集群模式
伪集群模式就是在单机环境下模拟集群的Zookeeper服务。
在zookeeper集群配置文件中,clientPort参数用来设置客户端连接zookeeper服务器的端口。
server.1=IP1:2888:3888中,
IP1指的是组成Zookeeper服务器的IP地址,
2888为组成zookeeper服务器之间的通信端口
3888为用来选举leader的端口
由于伪集群模式中,我们使用的是同一台服务器,也就是说,需要在单台机器上运行多个zookeeper实例,所以我们必须要保证多个zookeeper实例的配置文件的client端口不能冲突。
下面简单介绍一下如何在单台机器上建立伪集群模式。首先将zookeeper-3.4.9.tar.gz分别解压到server1,server2,server3目录下:
tar -zxvf zookeeper-3.4.9.tar.gz /home/jxwch/server1
tar -zxvf zookeeper-3.4.9.tar.gz /home/jxwch/server2
tar -zxvf zookeeper-3.4.9.tar.gz /home/jxwch/server3
然后在server1/data/目录下创建文件myid文件并写入“1”,
同样在server2/data/,目录下创建文件myid并写入“2”,server3进行同样的操作。
下面分别展示在server1/conf/、server2/conf/、server3/conf/目录下的zoo.cfg文件:
server1/conf/zoo.cfg文件
# Server 1
# The number of milliseconds of each tick
# 服务器与客户端之间交互的基本时间单元(ms)
tickTime=2000
# The number of ticks that the initial
# synchronization phase can take
# 此配置表示允许follower连接并同步到leader的初始化时间,它以tickTime的倍数来表示。当超过设置倍数的tickTime时间,则连接失败。
initLimit=10
# The number of ticks that can pass between
# sending a request and getting an acknowledgement
# Leader服务器与follower服务器之间信息同步允许的最大时间间隔,如果超过此间隔,默认follower服务器与leader服务器之间断开链接
syncLimit=5
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just
# example sakes.
# 保存zookeeper数据,日志路径
dataDir=/home/jxwch/server1/data
dataLogDir=/home/jxwch/server1/dataLog
# the port at which the clients will connect
# 客户端与zookeeper相互交互的端口
clientPort=2181
server.1= 127.0.0.1:2888:3888
server.2= 127.0.0.1:2889:3889
server.3= 127.0.0.1:2890:3890
#server.A=B:C:D 其中A是一个数字,代表这是第几号服务器;B是服务器的IP地址;C表示服务器与群集中的“领导者”交换信息的端口;当领导者失效后,D表示用来执行选举时服务器相互通信的端口。
# the maximum number of client connections.
# increase this if you need to handle more clients
# 限制连接到zookeeper服务器客户端的数量
maxClientCnxns=60
# Be sure to read the maintenance section of the
# administrator guide before turning on autopurge.
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
# The number of snapshots to retain in dataDir
#autopurge.snapRetainCount=3
# Purge task interval in hours
# Set to "0" to disable auto purge feature
#autopurge.purgeInterval=1
server2/conf/zoo.cfg文件
# Server 2
# The number of milliseconds of each tick
# 服务器与客户端之间交互的基本时间单元(ms)
tickTime=2000
# The number of ticks that the initial
# synchronization phase can take
# zookeeper所能接受的客户端数量
initLimit=10
# The number of ticks that can pass between
# sending a request and getting an acknowledgement
# 服务器与客户端之间请求和应答的时间间隔
syncLimit=5
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just
# example sakes.
# 保存zookeeper数据,日志路径
dataDir=/home/jxwch/server2/data
dataLogDir=/home/jxwch/server2/dataLog
# the port at which the clients will connect
# 客户端与zookeeper相互交互的端口
clientPort=2182
server.1= 127.0.0.1:2888:3888
server.2= 127.0.0.1:2889:3889
server.3= 127.0.0.1:2890:3890
#server.A=B:C:D 其中A是一个数字,代表这是第几号服务器;B是服务器的IP地址;C表示服务器与群集中的“领导者”交换信息的端口;当领导者失效后,D表示用来执行选举时服务器相互通信的端口。
# the maximum number of client connections.
# increase this if you need to handle more clients
#maxClientCnxns=60
#
# Be sure to read the maintenance section of the
# administrator guide before turning on autopurge.
#
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
#
# The number of snapshots to retain in dataDir
#autopurge.snapRetainCount=3
# Purge task interval in hours
# Set to "0" to disable auto purge feature
#autopurge.purgeInterval=1
server3/conf/zoo.cfg文件
# Server 3
# The number of milliseconds of each tick
# 服务器与客户端之间交互的基本时间单元(ms)
tickTime=2000
# The number of ticks that the initial
# synchronization phase can take
# zookeeper所能接受的客户端数量
initLimit=10
# The number of ticks that can pass between
# sending a request and getting an acknowledgement
# 服务器与客户端之间请求和应答的时间间隔
syncLimit=5
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just
# example sakes.
# 保存zookeeper数据,日志路径
dataDir=/home/jxwch/server3/data
dataLogDir=/home/jxwch/server3/dataLog
# the port at which the clients will connect
# 客户端与zookeeper相互交互的端口
clientPort=2183
server.1= 127.0.0.1:2888:3888
server.2= 127.0.0.1:2889:3889
server.3= 127.0.0.1:2890:3890
#server.A=B:C:D 其中A是一个数字,代表这是第几号服务器;B是服务器的IP地址;C表示服务器与群集中的“领导者”交换信息的端口;当领导者失效后,D表示用来执行选举时服务器相互通信的端口。
# the maximum number of client connections.
# increase this if you need to handle more clients
#maxClientCnxns=60
# Be sure to read the maintenance section of the
# administrator guide before turning on autopurge.
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
# The number of snapshots to retain in dataDir
#autopurge.snapRetainCount=3
# Purge task interval in hours
# Set to "0" to disable auto purge feature
#autopurge.purgeInterval=1
从上述三个代码清单可以发现,除了clientPort不同之外,dataDir和dataLogDir也不同。另外,不要忘记dataDir所对应的目录中创建的myid文件来指定对应的zookeeper服务器实例。
Zookeeper伪集群模式运行
当上述伪集群环境安装成功后就可以测试是否安装成功啦,我们可以尝尝鲜:
首先启动server1服务器:
cd server1/bin
bash zkServer.sh start
此时出现以下提示信息,表示启动成功:
打开zookeeper.out文件:
2017-02-23 16:17:46,419 [myid:] - INFO [main:QuorumPeerConfig@124] - Reading configuration from: /home/jxwch/server1/bin/../conf/zoo.cfg 2017-02-23 16:17:46,496 [myid:] - INFO [main:QuorumPeer$QuorumServer@149] - Resolved hostname: 127.0.0.1 to address: /127.0.0.1
2017-02-23 16:17:46,496 [myid:] - INFO [main:QuorumPeer$QuorumServer@149] - Resolved hostname: 127.0.0.1 to address: /127.0.0.1
2017-02-23 16:17:46,497 [myid:] - INFO [main:QuorumPeer$QuorumServer@149] - Resolved hostname: 127.0.0.1 to address: /127.0.0.1
2017-02-23 16:17:46,497 [myid:] - INFO [main:QuorumPeerConfig@352] - Defaulting to majority quorums 2017-02-23 16:17:46,511 [myid:1] - INFO [main:DatadirCleanupManager@78] - autopurge.snapRetainCount set to 3
2017-02-23 16:17:46,511 [myid:1] - INFO [main:DatadirCleanupManager@79] - autopurge.purgeInterval set to 0
2017-02-23 16:17:46,511 [myid:1] - INFO [main:DatadirCleanupManager@101] - Purge task is not scheduled. 2017-02-23 16:17:46,525 [myid:1] - INFO [main:QuorumPeerMain@127] - Starting quorum peer 2017-02-23 16:17:46,631 [myid:1] - INFO [main:NIOServerCnxnFactory@89] - binding to port 0.0.0.0/0.0.0.0:2181
2017-02-23 16:17:46,664 [myid:1] - INFO [main:QuorumPeer@1019] - tickTime set to 2000
2017-02-23 16:17:46,664 [myid:1] - INFO [main:QuorumPeer@1039] - minSessionTimeout set to -1
2017-02-23 16:17:46,664 [myid:1] - INFO [main:QuorumPeer@1050] - maxSessionTimeout set to -1
2017-02-23 16:17:46,665 [myid:1] - INFO [main:QuorumPeer@1065] - initLimit set to 10
2017-02-23 16:17:46,771 [myid:1] - INFO [main:FileSnap@83] - Reading snapshot /home/jxwch/server1/data/version-2/snapshot.400000015
2017-02-23 16:17:46,897 [myid:1] - INFO [ListenerThread:QuorumCnxManager$Listener@534] - My election bind port: /127.0.0.1:3888
2017-02-23 16:17:46,913 [myid:1] - INFO [QuorumPeer[myid=1]/0:0:0:0:0:0:0:0:2181:QuorumPeer@774] - LOOKING 2017-02-23 16:17:46,915 [myid:1] - INFO [QuorumPeer[myid=1]/0:0:0:0:0:0:0:0:2181:FastLeaderElection@818] - New election. My id = 1, proposed zxid=0x500000026
2017-02-23 16:17:46,922 [myid:1] - INFO [WorkerReceiver[myid=1]:FastLeaderElection@600] - Notification: 1 (message format version), 1 (n.leader), 0x500000026 (n.zxid), 0x1 (n.round), LOOKING (n.state), 1 (n.sid), 0x5 (n.peerEpoch) LOOKING (my state) 2017-02-23 16:17:46,940 [myid:1] - WARN [WorkerSender[myid=1]:QuorumCnxManager@400] - Cannot open channel to 2 at election address /127.0.0.1:3889 java.net.ConnectException: 拒绝连接 at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:579)
at org.apache.zookeeper.server.quorum.QuorumCnxManager.connectOne(QuorumCnxManager.java:381)
at org.apache.zookeeper.server.quorum.QuorumCnxManager.toSend(QuorumCnxManager.java:354)
at org.apache.zookeeper.server.quorum.FastLeaderElection$Messenger$WorkerSender.process(FastLeaderElection.java:452)
at org.apache.zookeeper.server.quorum.FastLeaderElection$Messenger$WorkerSender.run(FastLeaderElection.java:433)
at java.lang.Thread.run(Thread.java:745) 2017-02-23 16:17:46,943 [myid:1] - INFO [WorkerSender[myid=1]:QuorumPeer$QuorumServer@149] - Resolved hostname: 127.0.0.1 to address: /127.0.0.1 2017-02-23 16:17:46,944 [myid:1] - WARN [WorkerSender[myid=1]:QuorumCnxManager@400] - Cannot open channel to 3 at election address /127.0.0.1:3890 java.net.ConnectException: 拒绝连接 at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:579)
at org.apache.zookeeper.server.quorum.QuorumCnxManager.connectOne(QuorumCnxManager.java:381)
at org.apache.zookeeper.server.quorum.QuorumCnxManager.toSend(QuorumCnxManager.java:354)
at org.apache.zookeeper.server.quorum.FastLeaderElection$Messenger$WorkerSender.process(FastLeaderElection.java:452)
at org.apache.zookeeper.server.quorum.FastLeaderElection$Messenger$WorkerSender.run(FastLeaderElection.java:433)
at java.lang.Thread.run(Thread.java:745) 2017-02-23 16:17:46,944 [myid:1] - INFO [WorkerSender[myid=1]:QuorumPeer$QuorumServer@149] - Resolved hostname: 127.0.0.1 to address: /127.0.0.1
产生上述两条Waring信息是因为zookeeper服务的每个实例都拥有全局的配置信息,他们在启动的时候需要随时随地的进行leader选举,此时server1就需要和其他两个zookeeper实例进行通信,但是,另外两个zookeeper实例还没有启动起来,因此将会产生上述所示的提示信息。当我们用同样的方式启动server2和server3后就不会再有这样的警告信息了。
当三台服务器均成功启动后切换至server1/bin/目录下执行以下命令:
bash zkServer.sh status
终端出现以下提示信息:
说明server1服务器此时处于follower模式
同样切换至server2/bin目录下执行相同的命令,返回如下结果:
说明server2被选举为leader。