ZooKeeper的部署和测试
一背景
zookeeper是一个开源的分布式应用程序协调服务,是Apache Hadoop 的一个子项目。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、名字服务、分布式同步、组服务等。其原理是基于google发表的《The Chubby lock service for loosely-coupled distributed systems》论文。网上关于zookeeper的博客也很多,但很多讲的不细致,如如何测试部署成功。在学习别人的博客进行部署的过程中遇到了一些问题。所以写这篇博客主要是总结zookeeper的部署方法及在这过程中遇到的问题,提供更加详细的部署方案,希望能为其他初学者提供一些参考。
二所需环境和包
1. JDK 环境:
java JDK包可以到官网下载(这里提供所有版本的JDK下载地址:http://www.oracle.com/technetwork/java/archive-139210.html)
JDK安装可参考:
tar.gz方式
rpm方式: http://alan-hjkl.iteye.com/blog/1527179
JDK 环境是必须的,zookeeper是用java开发的,所以需要在JDK环境下运行。所以建议首先安装JDK,本人就是因为以为自己电脑上已经安装JDK,就直接部署zookeeper,在测试时并不成功,结果各种排错。
2. zookeeper 包:
下载地址:http://www.apache.org/dyn/closer.cgi/zookeeper/
三单机部署
1.创建工作目录
mkdir /usr/lib/zookeeper
- 1
2.创建data,logs文件
data :下存放节点ID
logs:用于下存放相关日志文件
mkdir/usr/lib/zookeeper/data
mkdir/usr/lib/zookeeper/logs
3.解压zookeeper到工作目录下
下载zookeeper的安装包之后, 解压到工作目录下(本文解压到/usr/lib/zookeeper).
tar -zxvf zookeeper-3.4.6.tar.gz/usr/lib/zookeeper
4.创建zoo.cfg
进入zookeeper目录下的conf子目录, 复制zoo_sample.cfg 并命名为zoo.cfg。
zookeeper服务器启动默认加载zoo.cfg文件,当然也可以命名为其他文件,但是在运行是需要指定cfg文件名。如命名为zk1.cfg时,启动zookeeper命令为:./zkServer.sh start zk1.cfg 。如果是zoo.cfg 启动时命令为:./zkServer.sh start
打开zoo.cfg 并修改相关配置
sudovi /usr/lib/zookeeper/zookeeper-3.4.6/conf/zoo.cfg
设置配置文件中的相关参数:
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/usr/lib/zookeeper/data
dataLogDir=/usr/lib/zookeeper/logs
clientPort=2181
参数说明:
- tickTime: zookeeper中使用的基本时间单位, 毫秒值
- initLimit: Follower在启动过程中,会从Leader同步所有最新数据,然后确定自己能够对外服务的起始状态。Leader允许Follower在initLimit时间内完成这个工作
- syncLimit:在运行过程中,Leader负责与ZK集群中所有机器进行通信,如果L发出心跳包在syncLimit之后,还没有从F那里收到响应,那么就认为这个F已经不在线了。
- dataDir: 数据目录. 可以是任意目录.本文制定/usr/lib/zookeeper/data
- dataLogDir: log目录, 同样可以是任意目录. 如果没有设置该参数, 将使用和dataDir相同的设置.
- clientPort: 监听client连接的端口号
在某些博客中还会涉及设置环境变量这一步。
在/etc/profile 文件中加入如下的内容:
#Set ZooKeeper Enviroment
exportZOOKEEPER_HOME=/usr/lib/zookeeper/zookeeper-3.4.6/
exportPATH=$PATH:$ZOOKEEPER_HOME/bin:$ZOOKEEPER_HOME/conf
但我经过尝试后发现,其实并不需要进行环境的设置就可以部署成功。单机部署就到此完成了,接下来就是验证下是否部署成功了。
五测试
这一步就是检验之前所部署的zookeeper是否能够成功运行。
1.启动服务:
首先进入到zookeeper-3.4.6的bin文件夹下,再启动zkServer.sh
cd/usr/lib/zookeeper/zookeeper-3.4.6/bin
./zkServer.sh start
或
/usr/lib/zookeeper/zookeeper-3.4.6/bin/zkServer.shstart
运行结果:
root@jaylon:/usr/lib/zookeeper/zookeeper-3.4.6/bin# ./zkServer.sh start
JMXenabled by default
Usingconfig:/usr/lib/zookeeper/zookeeper-3.4.6/bin/../conf/zoo.cfg
Startingzookeeper ... STARTED.
root@jaylon:/usr/lib/zookeeper/zookeeper-3.4.6/bin#
这里需要注意的是启动时命令为./zkServer.sh start。如果是启动zkServer.sh start的话会报错找不到命令错误。这点初学者需要小心。
2.检查运行状态
通过./zkServer.sh status来检查服务器运行状态
root@jaylon:/usr/lib/zookeeper/zookeeper-3.4.6/bin# ./zkServer.sh status
JMXenabled by default
Usingconfig:/usr/lib/zookeeper/zookeeper-3.4.6/bin/../conf/zoo.cfg
Mode:standalone
root@jaylon:/usr/lib/zookeeper/zookeeper-3.4.6/bin#
Mode:standalone 表明当前是单机模式,也表明部署成功。如果出现下面的情况说明部署不成功:
root@jaylon:/usr/lib/zookeeper/zookeeper-3.4.6/bin# ./zkServer.sh status
JMXenabled by default
Usingconfig:/usr/lib/zookeeper/zookeeper-3.4.6/bin/../conf/zoo.cfg
Errorcontacting service. Itis probablynotrunning.
root@jaylon:/usr/lib/zookeeper/zookeeper-3.4.6/bin#
如果出现这种情况检查以下几个方面:
1.JDK环境是否搭建好
2.检查zoo.cfg中的dataDir,dataLogDir路径是否有错误
3.启动客户端
如果确认没错的话,便可启动客户端进行交互测试。
运行bin下的zkCli.sh 文件,
具体指令:./zkCli.sh -server localhost:2181
localhost 表示指向本地地址(服务器地址)
2181 即是在配置文件zoo.cfg 中设置的clientPort端口号
意思是要建立与地址为localhost,端口号为2181的服务进行通信。如果运行该指令显示的结果如下,说明以及链接成功(即光标停止不动或最后一行显示[zk: localhost:2181(CONNECTED) 0] )
root@jaylon:/usr/lib/zookeeper/zookeeper-3.4.6/bin# ./zkCli.sh -server localhost:2181
Connecting tolocalhost:2181
2015-08-0709:39:06,957[myid:] - INFO [main:Environment@100] - Client environment:zookeeper.version=3.4.6-1569965, built on02/20/201409:09GMT
2015-08-0709:39:06,961[myid:] - INFO [main:Environment@100] - Client environment:host.name=jaylon
2015-08-0709:39:06,961[myid:] - INFO [main:Environment@100] - Client environment:java.version=1.7.0_80
2015-08-0709:39:06,965[myid:] - INFO [main:Environment@100] - Client environment:java.vendor=Oracle Corporation
2015-08-0709:39:06,965[myid:] - INFO [main:Environment@100] - Client environment:java.home=/usr/java/jdk1.7.0_80/jre
2015-08-0709:39:06,965[myid:] - INFO [main:Environment@100] - Client environment:java.class.path=/usr/lib/zookeeper/zookeeper-3.4.6/bin/../build/classes:/usr/lib/zookeeper/zookeeper-3.4.6/bin/../build/lib/*.jar:/usr/lib/zookeeper/zookeeper-3.4.6/bin/../lib/slf4j-log4j12-1.6.1.jar:/usr/lib/zookeeper/zookeeper-3.4.6/bin/../lib/slf4j-api-1.6.1.jar:/usr/lib/zookeeper/zookeeper-3.4.6/bin/../lib/netty-3.7.0.Final.jar:/usr/lib/zookeeper/zookeeper-3.4.6/bin/../lib/log4j-1.2.16.jar:/usr/lib/zookeeper/zookeeper-3.4.6/bin/../lib/jline-0.9.94.jar:/usr/lib/zookeeper/zookeeper-3.4.6/bin/../zookeeper-3.4.6.jar:/usr/lib/zookeeper/zookeeper-3.4.6/bin/../src/java/lib/*.jar:/usr/lib/zookeeper/zookeeper-3.4.6/bin/../conf:
2015-08-0709:39:06,966[myid:] - INFO [main:Environment@100] - Client environment:java.library.path=/usr/java/packages/lib/i386:/lib:/usr/lib
2015-08-0709:39:06,966[myid:] - INFO [main:Environment@100] - Client environment:java.io.tmpdir=/tmp
2015-08-0709:39:06,966[myid:] - INFO [main:Environment@100] - Client environment:java.compiler=<NA>
2015-08-0709:39:06,967[myid:] - INFO [main:Environment@100] - Client environment:os.name=Linux
2015-08-0709:39:06,967[myid:] - INFO [main:Environment@100] - Client environment:os.arch=i386
2015-08-0709:39:06,967[myid:] - INFO [main:Environment@100] - Client environment:os.version=3.13.0-32-generic
2015-08-0709:39:06,968[myid:] - INFO [main:Environment@100] - Client environment:user.name=root
2015-08-0709:39:06,968[myid:] - INFO [main:Environment@100] - Client environment:user.home=/root
2015-08-0709:39:06,968[myid:] - INFO [main:Environment@100] - Client environment:user.dir=/usr/lib/zookeeper/zookeeper-3.4.6/bin
2015-08-0709:39:06,972[myid:] - INFO [main:ZooKeeper@438] - Initiating client connection, connectString=localhost:2181sessionTimeout=30000watcher=org.apache.zookeeper.ZooKeeperMain$MyWatcher@e01430
Welcome toZooKeeper!
2015-08-0709:39:07,015[myid:] - INFO [main-SendThread(localhost:2181):ClientCnxn$SendThread@975] - Opening socket connection toserver localhost/127.0.0.1:2181.Will notattempt toauthenticate usingSASL (unknown error)
JLine support isenabled
2015-08-0709:39:07,034[myid:] - INFO [main-SendThread(localhost:2181):ClientCnxn$SendThread@852] - Socket connection established tolocalhost/127.0.0.1:2181, initiating session
[zk: localhost:2181(CONNECTING)0] 2015-08-0709:39:07,065[myid:] - INFO [main-SendThread(localhost:2181):ClientCnxn$SendThread@1235] - Session establishment complete onserver localhost/127.0.0.1:2181, sessionid = 0x14f05cde0f10001, negotiated timeout = 30000
WATCHER::
WatchedEvent state:SyncConnected type:None path:null
4 进行通信
现在进行客户端与服务端的通信,该步在3步基础上进行。在命令行输入help 会显示一些常用的通信指令:
[zk: localhost:2181(CONNECTED) 0] help
ZooKeeper -server host:port cmd args
connect host:port
getpath [watch]
ls path [watch]
setpath data [version]
rmr path
delquota [-n|-b] path
quit
printwatches on|off
create [-s] [-e] path data acl
stat path [watch]
close
ls2 path [watch]
history
listquota path
setAcl path acl
getAcl path
sync path
redo cmdno
addauth scheme auth
delete path [version]
setquota -n|-b val path
[zk: localhost:2181(CONNECTED) 1]
查看文件列表:
[zk: localhost:2181(CONNECTED) 1] ls/
[zookeeper]
新建文件:
[zk: localhost:2181(CONNECTED) 4] create/node node
Created /node
获取文件:
[zk: localhost:2181(CONNECTED) 5] get /node
node
cZxid= 0x100000008
ctime= Fri Aug 07 09:51:40 CST 2015
mZxid= 0x100000008
mtime= Fri Aug 07 09:51:40 CST 2015
pZxid= 0x100000008
cversion= 0
dataVersion= 0
aclVersion= 0
ephemeralOwner= 0x0
dataLength= 4
numChildren= 0
其他操作可以查看help。到这里已经完成了单机下的部署与测试了。接下就是要关闭服务。
5.关闭服务
操作完成记得关闭服务,不然端口一直被占用。在没有关闭服务的情况下再重启开启则会显示该服务正在运行。关闭代码如下:
root@jaylon:/usr/lib/zookeeper/zookeeper-3.4.6/bin# ./zkServer.sh stop
JMXenabled by default
Usingconfig:/usr/lib/zookeeper/zookeeper-3.4.6/bin/../conf/zoo.cfg
Stoppingzookeeper ... STOPPED
四伪集群模式部署
简单的说伪集群是指在单台机器中启动多个zookeeper进程, 并组成一个集群来模拟多台机器上的集群操作. 本文以启动3个zookeeper进程(节点)为例.
节点个数最好是奇数个,zookeeper集群是以宕机个数过半才会让整个集群宕机的,所以奇数个集群更佳。你可以设置3,5,7 个,原理上说节点越多越稳定。
1.创建虚拟节点
在本地建立三个节点,即三个文件夹来存放不同的节点配置
mkdir /usr/lib/zk/
mkdir /usr/lib/zk/server1
mkdir /usr/lib/zk/server2
mkdir /usr/lib/zk/server3
并在每个节点文件夹下建立data,logs文件夹,类似单机模式。将zookeeper软件包分别解压到三文件夹下(server1,server2,server3)。和单模式下一样,在每个节点的zookeeper-3.4.6/conf下创建zoo.cfg 。做法与单机模式一样。
2.配置不同节点的zoo.cfg
现在有3个节点,有三个配置文件(zoo.cfg)。所以需要对三个配置文件分别进行配置。
节点1
/usr/lib/zk/server1/zookeeper-3.4.6/conf/zoo.cfg
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/usr/lib/zk/server1/data #注意这边路劲的不同
dataLogDir=/usr/lib/zk/server1/logs #注意这边路劲的不同
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.服务号=服务地址:服务端口:通信端口
- 1
服务号:为每个节点分配对应的id
服务地址:服务所在地址,因为现在用的是单机所以地址都是本地
服务端口:和clientPort端口是不同的
在设置过程中服务端口和通信端口应该不同,每个节点的服务端口和通信端口也不同,以防止端口冲突。
其他文件节点zoo.cfg配置基本一样,不同的在于dataDir,dataLogDir和clientPort
节点2
/usr/lib/zk/server2/zookeeper-3.4.6/conf/zoo.cfg
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/usr/lib/zk/server2/data #注意这边路劲的不同server2
dataLogDir=/usr/lib/zk/server2/logs #注意这边路劲的不同server2
clientPort=2182 #端口号每个节点不同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
节点3
/usr/lib/zk/server3/zookeeper-3.4.6/conf/zoo.cfg
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/usr/lib/zk/server3/data #注意这边路劲的不同server3
dataLogDir=/usr/lib/zk/server3/logs #注意这边路劲的不同server3
clientPort=2183 #端口号每个节点不同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
3.配置不同节点上的myid
在每个节点的data文件夹下分别创建myid文件(没有后缀)。并在每个myid文件里只写上该节点的id如:
server1/data/myid 里写1
server2/data/myid 里写2
server3/data/myid 里写3
4.启动
与单机模式不同,集群模式需要同时启动所有节点上的服务
建议在/root 下建立一个start.sh 文件到时只需要启动该文件则可以将三个服务同时启动,则不用分别进入每个文件夹下启动zkServer.sh 。
start.sh 文件内容如下:
/usr/lib/zk/server1/zookeeper-3.4.6/bin/zkServer.shstart
/usr/lib/zk/server2/zookeeper-3.4.6/bin/zkServer.shstart
/usr/lib/zk/server3/zookeeper-3.4.6/bin/zkServer.shstart
启动服务:
root@jaylon:~# gedit start.sh
root@jaylon:~# ./start.sh
JMX enabled by default
Using config: /usr/lib/zk/server1/zookeeper/bin/../conf/zoo.cfg
Starting zookeeper ...STARTED
JMX enabled by default
Using config: /usr/lib/zk/server2/zookeeper/bin/../conf/zoo.cfg
Starting zookeeper ...STARTED
JMX enabled by default
Using config: /usr/lib/zk/server3/zookeeper/bin/../conf/zoo.cfg
Starting zookeeper ...STARTED
5.测试
检查服务是否正常启动。我们可以写一个指令文件status.sh 内容如下(和start.sh 不同的在于将start改成status):
/usr/lib/zk/server1/zookeeper-3.4.6/bin/zkServer.sh status
/usr/lib/zk/server2/zookeeper-3.4.6/bin/zkServer.sh status
/usr/lib/zk/server3/zookeeper-3.4.6/bin/zkServer.sh status
启动检查:
root@jaylon-Lenovo-G460:~# ./status.sh
JMX enabled bydefault
Usingconfig: /usr/lib/zk/server1/zookeeper/bin/../conf/zoo.cfg
Mode: leader
JMX enabled bydefault
Usingconfig: /usr/lib/zk/server2/zookeeper/bin/../conf/zoo.cfg
Mode: follower
JMX enabled bydefault
Usingconfig: /usr/lib/zk/server3/zookeeper/bin/../conf/zoo.cfg
Mode: follower
从mode中可以看到每个节点的状态。节点1 是leader 其他两个节点是follower。
ZooKeeper需要在所有的服务(可以理解为服务器)中选举出一个Leader,然后让这个Leader来负责管理集群。此时,集群中的其它服务器则成为此Leader的Follower。并且,当Leader故障的时候,需要ZooKeeper能够快速地在Follower中选举出下一个Leader
6.通信
从任意节点下启动一个客户端链接任意节点的服务端口。
如启动节点3的客户端链接节点2的服务:
cd/usr/lib/zk/server3/zookeeper-3.4.6/bin
./zkCli.sh -server localhost:2182
链接成功后的通信与链接失败的问题解决也可以参考单机模式。
7.关闭服务
root@jaylon:/usr/lib/zk/server1/zookeeper-3.4.6/bin/zkServer.sh stop
root@jaylon:/usr/lib/zk/server2/zookeeper-3.4.6/bin/zkServer.sh stop
root@jaylon:/usr/lib/zk/server3/zookeeper-3.4.6/bin/zkServer.sh stop
四问题总结
安装过程中常遇到的问题就是部署完如何检验部署成功,这也是很多博文没有提供的。另外就是部署不成功,问题如何解决。以下总结自己遇到的问题,及觉得容易忽略的问题:
- JDK没有安装好就启动了zookeeper服务
- 配置文件zoo.cfg 中的路径写错了,与具体文件没对应上
- 每个节点的clientPort 设置相同了
- 每个节点的myid文件的内容是否和对应节点id一样
- zoo.cfg 的服务端口和通信端口设置是否正确,端口是否被占用
五参考资料
http://coolxing.iteye.com/blog/1871009
http://blog.chinaunix.net/uid-20498361-id-3184380.html
另一种集群配置方式:http://blog.fens.me/hadoop-zookeeper-intro/