安装Zookeeper
安装成功后进入zookeeper/bin 目录下启动命令: ./zkServer.sh start ;查看状态命令: ./zkServer.sh status。
zookeeper集群搭建
集群搭建问题参考:https://blog.csdn.net/hy_coming/article/details/84202525;
状态查询问题 参考 https://blog.csdn.net/a_drjiaoda/article/details/83651220 。
一、什么是zookeeper(摘自百度百科)
ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。
ZooKeeper的目标就是封装好复杂易出错的关键服务,将简单易用的接口和性能高效、功能稳定的系统提供给用户。
ZooKeeper包含一个简单的原语集, [1] 提供Java和C的接口。
ZooKeeper代码版本中,提供了分布式独享锁、选举、队列的接口,代码在zookeeper-3.4.3\src\recipes。其中分布锁和队列有Java和C两个版本,选举只有Java版本。
ZooKeeper是以Fast Paxos算法为基础的,Paxos 算法存在活锁的问题,即当有多个proposer交错提交时,有可能互相排斥导致没有一个proposer能提交成功,而Fast Paxos作了一些优化,通过选举产生一个leader (领导者),只有leader才能提交proposer,具体算法可见Fast Paxos。因此,要想弄懂ZooKeeper首先得对Fast Paxos有所了解。 [3]
ZooKeeper的基本运转流程:
1、选举Leader。
2、同步数据。
3、选举Leader过程中算法有很多,但要达到的选举标准是一致的。
4、Leader要具有最高的执行ID,类似root权限。
5、集群中大多数的机器得到响应并接受选出的Leader。
我的理解就是这个框架能够更好的协调数据和服务器之间的关系,将服务器的资源运用最大化,同时还能够在系统发生不可预测状况规避一些不必要的风险等。
二、环境搭建
本人建议这个要从分布式集群基础环境搭建的基础上去做就会更加的方便,条例更加的清楚,还有linux系统java环境也是必须的,因为zookeeper就是用java写的,我把他分为以下几步:、
第一步:VMware搭建分布式集群基础环境:https://blog.csdn.net/hy_coming/article/details/82990632
第二步:搭建java环境:https://blog.csdn.net/hy_coming/article/details/82990296(这个是centos7的搭建,不同的版本就参照不同的教程)
第三步:zookeeper搭建
- 官网下载zookeeper,下载教程参考:https://jingyan.baidu.com/article/a24b33cd3947ee19fe002bcb.html
- 如果上面基础基础的分布式集群环境搭建好了之后,我们应该可以通过secureCR和secureFX(或者是其他的工具)连接上虚拟机了,首先需要验证环境的可用性,执行java -version,查看java环境是否正常,出现以下信息说明正常
-
-
java version "1.8.0_151"
-
Java(TM) SE Runtime Environment (build 1.8.0_151-b12)
-
Java HotSpot(TM) 64-Bit Server VM (build 25.151-b12, mixed mode)
-
- 接着验证各台主机的防火墙是否关闭(这个问题是出现问题最大的地方,这里我将他放在前面来验证解决), 针对不同的linux系统版本执行不同的命令:
Ubuntu(ubuntu-12.04-desktop-amd64)
查看防火墙状态:ufw status
关闭防火墙:ufw disable
---------------------------------------------------------------
centos6.0查看防火墙状态:service iptables status
关闭防火墙:chkconfig iptables off #开机不启动防火墙服务
--------------------------------------------------------------
centos7.0(默认是使用firewall作为防火墙,如若未改为iptables防火墙,使用以下命令查看和关闭防火墙)
查看防火墙状态:firewall-cmd --state
关闭防火墙:systemctl stop firewalld.service
-
每台机器都需要查看,若没有关闭,一定要关闭,否则启动zookeeper的时候会报“java.net.NoRouteToHostException: 没有到主机的路由”这样的错误,接下来开始安装zookeeper相关文件(这里一一台虚拟机为例,每台虚拟机都要执行同样的操作)
-
首先要注意的是在生产环境中目录结构要定义好,防止在项目过多的时候找不到所需的项目。 我把目录统一放在/opt下面,该目录一般存放主机额外安装的软件。(当然也可以放在其他的你愿意的目录之下)
-
// 首先创建zookeeper项目目录
-
mkdir zookeeper // 项目目录
-
cd zookeeper // 进入项目目录
-
mkdir zkdata // 存放快照日志(名字可以自己定义)
-
mkdir zkdatalog // 存放事物日志(名字可以自己定义)
然后将之前下载好的zookeeper文件通过文件传输工具传输到虚拟机中,我放在了/opt/zookeeper项目文件下,解压文件
-
cd /opt/zookeeper // 进入下载目录
-
tar -zxvf zookeeper-3.4.11.tar.gz // 解压文件
-
-
增加配置文件,进入到解压好的zookeeper的conf目录中,查看:
-
//进入conf目录
-
cd /opt/zookeeper/zookeeper-3.4.11/conf
-
//查看
-
-rw-rw-r--. 1 1000 1000 535 Feb 20 2014 configuration.xsl
-
-rw-rw-r--. 1 1000 1000 2161 Feb 20 2014 log4j.properties
-
-rw-rw-r--. 1 1000 1000 922 Feb 20 2014 zoo_sample.cfg
zoo_sample.cfg这个文件是官方给我们的zookeeper的样板文件。我们需要复制一份名为zoo.cfg的文件,zoo.cfg是zookeeper官方指定的文件命名规则。我们以在第一台虚拟机上的操作为例(上面的操作都是在第一台虚拟机上,你需要在每台虚拟机上都执行上述以及本次操作):
-
// 复制zoo.cfg文件
-
cp zoo_sample.cfg zoo.cfg
-
// 打开zoo.cfg文件,然后按后面的配置信息进行配置
-
vim zoo.zfg
在zoo.cfg配置文件需要填入的信息。
-
tickTime=2000
-
initLimit=10
-
syncLimit=5
-
dataDir=/opt/zookeeper/zkdata
-
dataLogDir=/opt/zookeeper/zkdatalog
-
clientPort=2181
-
// 此处的IP就是你所操作的三台虚拟机的IP地址,每台虚拟机的zoo.cfg中都需要填入这三个地址。第一个端口是master和slave之间的通信端口,默认是2888,第二个端口是leader选举的端口,集群刚启动的时候选举或者leader挂掉之后进行新的选举的端口默认是3888
-
server.1=虚拟机1 ip:2888:3888
-
server.2=虚拟机2 ip:2888:3888
-
server.3=虚拟机3 ip:2888:3888
-
// server.1 这个1是服务器的标识也可以是其他的数字, 表示这个是第几号服务器,用来标识服务器,这个标识要写到快照目录下面myid文件里
创建myid文件。以现在所在的第一台虚拟机192.168.172.10为例,对应server.1,通过上边的配置信息可以查到。创建myid文件的目的是为了让zookeeper知道自己在哪台服务器上,例如现在所在的虚拟机是192.168.172.10,它对应的id是1,那么就在myid文件中写入1.另外两台虚拟机上也需要创建myid文件并写入相应的id,id根据zoo.cfg文件中的IP地址查询。
-
echo "1" > /opt/zookeeper/zkdata/myid
-
echo "2" > /opt/zookeeper/zkdata/myid
-
echo "3" > /opt/zookeeper/zkdata/myid
-
-
启动zookeeper,进入到zookeeper的bin目录下
-
cd /opt/zookeeper/zookeeper-3.4.11/bin/
-
// 启动服务 (注意!三台虚拟机都要进行该操作)
-
./zkServer.sh start
-
// 检查服务器状态
-
./zkServer.sh status
-
// 显示如下
-
JMX enabled by default
-
Using config: /opt/zookeeper/zookeeper-3.4.6/bin/../conf/zoo.cfg
-
Mode: follower #他是主节点leader还是从节点follower
-
三、配置文件说明
- myid文件和server.myid 在快照目录下存放的标识本台服务器的文件,他是整个zk集群用来发现彼此的一个重要标识。
- zoo.cfg配置文件。zoo.cfg文件是zookeeper配置文件,在conf目录里。
-
// tickTime:
-
这个时间是作为 Zookeeper 服务器之间或客户端与服务器之间维持心跳的时间间隔,也就是每个 tickTime 时间就会发送一个心跳。
-
// initLimit:
-
这个配置项是用来配置 Zookeeper 接受客户端(这里所说的客户端不是用户连接 Zookeeper 服务器的客户端,而是 Zookeeper 服务器集群中连接到 Leader 的 Follower 服务器)初始化连接时最长能忍受多少个心跳时间间隔数。当已经超过 5个心跳的时间(也就是 tickTime)长度后 Zookeeper 服务器还没有收到客户端的返回信息,那么表明这个客户端连接失败。总的时间长度就是 5x2000(毫秒)=10 秒
-
// syncLimit:
-
这个配置项标识 Leader 与Follower 之间发送消息,请求和应答时间长度,最长不能超过多少个 tickTime 的时间长度,总的时间长度就是5x2000(毫秒)=10秒
-
// dataDir:
-
快照日志的存储路径
-
// dataLogDir:
-
事物日志的存储路径,如果不配置这个那么事物日志会默认存储到dataDir制定的目录,这样会严重影响zk的性能,当zk吞吐量较大的时候,产生的事物日志、快照日志太多
-
// clientPort:
-
这个端口就是客户端连接 Zookeeper 服务器的端口,Zookeeper 会监听这个端口,接受客户端的访问请求。修改他的端口改大点
-
四、错误盘点
在我们配置好之后启动的时候难免会出现错误,那么我们怎么知道错误原因呢?其实这个zookeeper团队早就为我们好了,就是就是在/opt/zookeeper/zookeeper-3.3.6/bin/zookeeper.out文件里面,我们只需要查看这个文件就能够定位到问题所在,这里只能把问题总结一下了:
在用./zkServer.sh start
命令运行zookeeper后,zookeeper节点显示正常启动,但是用zkServer.sh status
命令查看zookeeper节点的状态时,发现并没有正常运行,出现:
Error contacting service. It is probably not running.
我试着重新./zkServer.sh start
,却无法启动,显示:
already running as process 1854
对于这个问题,网上有很多答案,试了一遍:
- zoo.cfg配置文件中指定目录却没有创建! 创建相应目录即可。
//我的目录配置没有问题 - zoo.cfg中dataDir指定路径为Myid文件的路径。Myid内容与:
server.?=192.168.172.10:12888:13888
中所设置?
是否一致?
//我的设置是一致的! - 使用
service iptables stop
关闭防火墙.(按照的你的版本查看或者关闭防火墙)
//这个确实没关,但用的命令不是service iptables stop
,而是:
systemctl stop firewalld.service #停止firewall
systemctl disable firewalld.service #禁止firewall开机启动
关闭后确实起作用了,但是第二天重新启动时,刚开始运行还没问题,到中午吃完饭回来就又出现了,所以应该不是防火墙的问题:
Error contacting service. It is probably not running.
- 打开zkServer.sh 找到
status)
STAT=echo stat | nc localhost $(grep clientPort "$ZOOCFG" | sed -e 's/.*=//') 2> /dev/null| grep Mode
在nc
与localhost
之间加上 -q 1
(是数字1
而不是字母l
).如果已存在则去掉。
// 但是我的zkServer.sh中没有这一行。
- 2181端口被占用
使用netstat -anp | grep 12181
查看,确实发现有程序占用这个端口,但是kill掉以后还是不能启动zookeeper。
于是我不再管虚拟机1,又依次开启虚拟机2 和虚拟机3,其中虚拟机2和虚拟机1一样,都是:
Error contacting service. It is probably not running.
但是神奇的事情发生了,我开启虚拟机3的时候,是成功的,值得注意的是这里显示的zookeeper状态时leader:
[root@localhost bin]# ./zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /opt/zookeeper/zookeeper-3.4.11/bin/../conf/zoo.cfg
Mode: leader
也就是说虚拟机3所在的zookeeper节点是leader,然后再开启虚拟机2和虚拟机1,就没问题了。但是不知道为什么虚拟机3默认为leader,可能我之前在哪里配置过我不记得了(可能性不大),也可能跟zookeeper选举leader的机制有关系,这个需要深入了解。
不过现在可以得出这样的结论:zookeeper的开启顺序是有要求的,要先开启leader,剩下的节点才能正常启动。
成功运行后,三台虚拟机,一台是leader,另外两台是follower。
这个问题是由于zoo.cfg文件中的server
写错了,写成了servers
。所以server
写错可能导致zookeeper运行在单机模式下。
启动失败之后,再次启动就会一直报already running as process 1854,这样的错误,现在的你把问题找到,修改文件或问题,要求重新启动,必须先kill 1845这个进程,然后在正常启动就行了
今天在使用storm时,需要启动zookeeper依赖集群。于是使用命令启动zookeeper集群,使用命令bin/zkServer.sh start
-
[root@master bin]# ./zkServer.sh start
-
ZooKeeper JMX enabled by default
-
Using config: /usr/zookeeper/zookeeper-3.4.10/bin/../conf/zoo.cfg
-
Starting zookeeper ... STARTED
-
[root@master bin]# jps
-
2936 Jps
-
2924 QuorumPeerMain
为了查看zookeeper在master节点上是否启动成功,使用jps命令查看相关进程是否启动,如上图QuorumPeerMain进程已成功启动。此时,小厨突然想看看master节点上zookeeper的状态,到底是leader还是follower,确保节点成功启动。使用命令bin/zkServer.sh status,此时却意外的出现了异常。如下图
-
[root@master bin]# ./zkServer.sh status
-
ZooKeeper JMX enabled by default
-
Using config: /usr/zookeeper/zookeeper-3.4.10/bin/../conf/zoo.cfg
-
Error contacting service. It is probably not running.
于是去bin目录下去查看zookeeper.out输出日志:
-
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:562)
-
at org.apache.zookeeper.server.quorum.QuorumCnxManager.connectAll(QuorumCnxManager.java:614)
-
at org.apache.zookeeper.server.quorum.FastLeaderElection.lookForLeader(FastLeaderElection.java:843)
-
at org.apache.zookeeper.server.quorum.QuorumPeer.run(QuorumPeer.java:913)
-
2018-11-02 09:42:48,188 [myid:1] - INFO [QuorumPeer[myid=1]/0:0:0:0:0:0:0:0:2181:QuorumPeer$QuorumServer@167] - Resolved hostname: 192.168.83.133 to address: /192.168.83.133
-
2018-11-02 09:42:48,188 [myid:1] - INFO [QuorumPeer[myid=1]/0:0:0:0:0:0:0:0:2181:FastLeaderElection@852] - Notification time out: 60000
报错为:拒绝连接,于是排查了一遍节点的配置,确定都正确,此时有网友列出可能是myid重复了,于是去各节点查看id的设置
发现在data目录下的myid各节点直接并无重复,排除不是myid重复的原因。于是我启动了第二台和第三台节点上的zookeeper,并查看相关启动线程和zookeeper的集群状态
发现两个从节点都可以正常的查看状态。此时问题浮出水面:导致无法查看status的原因是,当小厨在master节点上执行bin/zkServer.sh status命令时,只有master节点的zookeeper进程启动了,其他节点的进程并没有启动,master节点无法与slave节点交互。由于zookeeper集群是依靠选举机制来产生leader和follower,当无法交互时也就无法选出leader和follower,因此执行status命令时,无法获取节点的状态。总结:只启动一台节点时,无法获取zookeeper的节点状态。
当正确启动另外两个节点时,master的status如下:
-
[root@master bin]# ./zkServer.sh status
-
ZooKeeper JMX enabled by default
-
Using config: /usr/zookeeper/zookeeper-3.4.10/bin/../conf/zoo.cfg
-
Mode: follower
至此,解决问题。