ZooKeeper(三)ZooKeeper的安装、配置和启动

Windows下单节点的安装和启动

1.下载

此处使用的是 3.4.10 Release 版本,官网下载地址:
http://mirrors.hust.edu.cn/apache/zookeeper/

2.安装

解压到指定目录下D:\Software\zookeeper-3.4.8\,进入ZooKeeper的配置文件目录(D:\Software\zookeeper-3.4.8\conf),复制zoo_sample.cfg文件并重命名为zoo.cfg
主要修改一下ZooKeeper数据和日志储存位置,改成当前windows系统中的某个目录,具体配置文件如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# The number of milliseconds of each tick
tickTime=2000
# The number of ticks that the initial
# synchronization phase can take
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.
dtaDir=D:\data\zookeeper\data
dtaLogDir=D:\data\zookeeper\log
# the port at which the clients will connect
clientPort=2181
# 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

3.启动

进入到bin目录,双击执行zkServer.cmd,这个脚本中会启动一个java进程。

启动后用jps -l -v命令可以看到QuorumPeerMain的进程,这是ZooKeeper的进程。

也可以在bin目录下,使用命令zkCli.cmd 127.0.0.1:2181启动客户端连接一下,看是否能进入到ZooKeeper的命令行操作界面。

至此,成功安装,很简单。

ZooKeeper的配置说明

ZooKeeper的配置文件是zoo.cfg,如果该文件不存在,会使用zoo_sample.cfg
zoo.cfg是ZooKeeper的主要配置文件,因为Zookeeper是一个集群服务,集群的每个节点都需要这个配置文件。在zoo.cfg这个配置文件里没有跟特定节点相关的配置,所以每个节点上的这个zoo.cfg都是相同的,这样非常便于管理,比如我们可以把这个文件提交到版本控制里管理起来。其实这给我们设计集群系统的时候也是个提示:集群系统一般有很多配置,应该尽量将通用的配置和特定每个服务的配置(比如服务标识)分离,这样通用的配置在不同服务之间copy就行了。
下面是详细的配置字段解释:

  • clientPort=2181
    这是客户端连接zookeeper服务的端口,是一个TCP port。
  • dataDir=/opt/zookeeper/data
    存放ZooKeeper数据的目录。
  • dataDir=/opt/zookeeper/data
    存放ZooKeeper日志的目录。dataLogDir如果没提供的话使用的则是dataDir。ZooKeeper的持久化都存储在这两个目录里。dataLogDir里是放到的顺序日志(WAL)。而dataDir里放的是内存数据结构的snapshot,便于快速恢复。为了达到性能最大化,一般建议把dataDir和dataLogDir分到不同的磁盘上,这样就可以充分利用磁盘顺序写的特性。
  • tickTime:
    这是个时间单位定量。比如tickTime=1000,这就表示在ZooKeeper里1 tick表示1000 ms,所有其他用到时间的地方都会用多少tick来表示。比如 syncLimit = 2 就表示fowller与leader的心跳时间是2 tick。
  • maxClientCnxns:
    对于一个客户端的连接数限制,默认是60,这在大部分时候是足够了。但是在我们实际使用中发现,在测试环境经常超过这个数,经过调查发现有的团队将几十个应用全部部署到一台机器上,以方便测试,于是这个数字就超过了。
  • minSessionTimeout, maxSessionTimeout:
    一般客户端连接zookeeper的时候,都会设置一个session timeout,如果超过这个时间client没有与zookeeper server有联系,则这个session会被设置为过期。但是这个时间不是客户端可以无限制设置的,服务器可以设置这两个参数来限制客户端设置的范围。
  • autopurge.snapRetainCount,autopurge.purgeInterval:
    客户端在与zookeeper交互过程中会产生非常多的日志,而且zookeeper也会将内存中的数据作为snapshot保存下来,这些数据是不会被自动删除的,这样磁盘中这样的数据就会越来越多。不过可以通过这两个参数来设置,让ZooKeeper自动删除数据。autopurge.purgeInterval就是设置多少小时清理一次。而autopurge.snapRetainCount是设置保留多少个snapshot,之前的则删除。不过如果你的集群是一个非常繁忙的集群,然后又碰上这个删除操作,可能会影响ZooKeeper集群的性能,所以一般会让这个过程在访问低谷的时候进行,但是遗憾的是ZooKeeper并没有设置在哪个时间点运行的设置,所以有的时候我们可以禁用这个自动删除的功能,而在服务器上配置一个cron脚本,然后在凌晨来做这件事情。

以上就是zoo.cfg里的一些基本配置了。但这是对于单个节点的配置,对于ZooKeeper集群的需要配置如下两点:

  1. 配置集群中服务的列表
    1
    2
    3
    server.1=127.0.0.1:20881:30881
    server.2=127.0.0.1:20882:30882
    server.3=127.0.0.1:20883:30883

在上面的例子中,我把三个ZooKeeper服务放到同一台机器上。上面的配置中有两个TCP port。后面一个是用于ZooKeeper选举用的,而前一个是Leader和Follower或Observer交换数据使用的。我们还注意到server.后面的数字。这个叫做myid。

  1. 配置-myid

在dataDir里会放置一个myid文件,里面就一个数字,用来唯一标识这个服务。这个id是很重要的,一定要保证整个集群中唯一。ZooKeeper会根据这个id来取出server.x上的配置。比如当前id为1,则对应着zoo.cfg里的server.1的配置。myid的值在选举master的时候也会用到。

Linux下ZooKeeper集群的安装

  1. 开启三台虚拟机server_01(192.168.128.1),server_02(192.168.128.2),server_03(192.168.128.3),并都使用root用户登录。这三个Linux系统上都装好JDK,并配置了JAVA_HOME环境变量。
  2. 在server_01上解压 zookeeper-3.4.11.tar.gz 文件到 /opt 目录下。
    tar -zxvf /root/software/zookeeper-3.4.11.tar.gz -C /opt
  3. 进入到解压后的zookeeper配置文件目录,
    cd /opt/zookeeper-3.4.11/conf
    还是和单节点安装一样,复制zoo_sample.cfg文件,并命名新的文件名为 zoo.cfg。
    cp zoo_sample.cfg zoo.cfg
    vim zoo.cfg
    添加如下内容:

    1
    2
    3
    4
    5
    6
    7
    dataDir=/root/zookeeper-data
    dataLogDir=/root/zookeeper-log

    #主机ip, 心跳端口、数据端口
    server.1=192.168.128.1:2888:3888 # 1表示myid为1的zookeeper
    server.2=192.168.128.2:2888:3888
    server.3=192.168.128.3:2888:3888
  4. 创建存储zookeeper数据和日志的两个文件夹。
    mkdir /root/zookeeper-data
    mkdir /root/zookeeper-log
    并在数据目录下创建一个myid文件,该文件存储该服务器对应的myid值。
    cd /root/zookeeper-data
    cat 1 > myid

  5. 其他两台服务器也做相应的设置,myid设置成2和3,可以使用scp命令将ZooKeeper的解压目录直接拷贝过去。

  6. 启动三台服务器上的ZooKeeper。cd到每台服务器上的$ZOOKEEPER_HONE/bin目录,执行命令:
    zkServer.sh start

  7. 三台服务器上的ZooKeeper都启动后,可以查看哪个是leader,哪个是follower。
    zkServer.sh status

至此,我们的ZooKeeper集群就启动起来了。

PS:我一开始在运行 zkServer.sh status 命令时报错了,显示如下:

1
2
3
JMX enabled by default
Using config: /usr/local/zk/bin/../conf/zoo.cfg
Error contacting service. It is probably not running.

查看bin目录下的 zookeeper.out 日志,显示是当前服务器和其它服务器通过3888端口通信时,连接被拒绝。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2017-11-15 06:26:50,306 [myid:1] - WARN  [QuorumPeer[myid=1]/0:0:0:0:0:0:0:0:2181:QuorumCnxManager@584] - Cannot open channel to 2 at election address server_02/192.168.128.2:3888
java.net.ConnectException: Connection refused (Connection refused)
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:589)
at org.apache.zookeeper.server.quorum.QuorumCnxManager.connectOne(QuorumCnxManager.java:558)
at org.apache.zookeeper.server.quorum.QuorumCnxManager.connectAll(QuorumCnxManager.java:610)
at org.apache.zookeeper.server.quorum.FastLeaderElection.lookForLeader(FastLeaderElection.java:845)
at org.apache.zookeeper.server.quorum.QuorumPeer.run(QuorumPeer.java:957)
2017-11-15 06:26:50,308 [myid:1] - INFO [QuorumPeer[myid=1]/0:0:0:0:0:0:0:0:2181:QuorumPeer$QuorumServer@184] - Resolved hostname: server_02 to address: server_02/192.168.128.2
2017-11-15 06:26:50,312 [myid:1] - WARN [QuorumPeer[myid=1]/0:0:0:0:0:0:0:0:2181:QuorumCnxManager@584] - Cannot open channel to 3 at election address server_03/192.168.128.3:3888
java.net.ConnectException: Connection refused (Connection refused)
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:589)
at org.apache.zookeeper.server.quorum.QuorumCnxManager.connectOne(QuorumCnxManager.java:558)
at org.apache.zookeeper.server.quorum.QuorumCnxManager.connectAll(QuorumCnxManager.java:610)
at org.apache.zookeeper.server.quorum.FastLeaderElection.lookForLeader(FastLeaderElection.java:845)
at org.apache.zookeeper.server.quorum.QuorumPeer.run(QuorumPeer.java:957)
2017-11-15 06:26:50,313 [myid:1] - INFO [QuorumPeer[myid=1]/0:0:0:0:0:0:0:0:2181:QuorumPeer$QuorumServer@184] - Resolved hostname: server_03 to address: server_03/192.168.128.3
2017-11-15 06:26:50,314 [myid:1] - INFO [QuorumPeer[myid=1]/0:0:0:0:0:0:0:0:2181:FastLeaderElection@854] - Notification time out: 60000

如何解决的:在配置ZooKeeper的配置文件时,使用ip的方式。

而原来我是使用的如下的主机名的方式:

1
2
3
server.1=server_01:2888:3888   
server.2=server_02:2888:3888
server.3=server_03:2888:3888

原因:在三台服务器的/etc/hosts文件中都要配置了ip和主机名的对应关系。对应每一个服务器,不仅要配置回环地址的名字,还要另外单独配置自己ip对应的主机名。也就是说在hosts文件中,除了127.0.0.1和::1,还要配置本机ip对应的主机名。如果要配置成主机名的形式,hosts文件配置成如下就可以了。

1
2
3
4
5
6
127.0.0.1   localhost
::1 localhost
192.168.128.1 server01
192.168.128.2 server02
192.168.128.3 server03
192.168.128.4 server04

------ 本文完 ------