CentOS搭建zookeeper集群


ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,也是Hadoop和Hbase的重要组件 。ZooKeeper的选主过程是以Fast Paxos算法为基础的。前面我有文章写过Paxos算法,Paxos 算法存在活锁的问题,即当有多个proposer交错提交时,有可能互相排斥导致没有一个proposer能提交成功,而Fast Paxos对Paxos进行了优化。通过选举产生一个leader (领导者),只有leader才能提交proposer,具体算法可见Fast Paxos 。因此,要想弄懂ZooKeeper首先得对Fast Paxos有所了解 。因为此算法的特性,所以要求Zookeeper集群的节点数最好为奇数个,而且算法保证如果集群中Leader宕机,只要剩余节点在总节点数的半数以上,就会重新选主,继续对外提供服务。也正是由于这个原因,使得Zookeeper是一个高效的分布式协调服务,可以提供配置信息管理、命名、分布式同步、集群管理、数据库切换等服务,被广泛应用于分布式应用场景中。本人在工作中也使用了很久,故此记录一下。

首先准备环境:三个虚拟机,jdk1.8。

ip地址 系统
192.168.31.135 CentOS 7
192.168.31.136 CentOS 7
192.168.31.137 CentOS 7

1 . JDK安装

(1) . jdk 1.8下载地址:jdk-8u181-linux-x64.tar.gz 。进入官网后选择Linux 64位下载

创建一个用户文件夹

mkdir /user/java

将要下载好的jdk包上传到这个目录下,然后进入到这个目录执行如下命令

tar -zxvf jdk-8u181-linux-x64.tar.gz

解压缩包后 /user/java 会多出一个 jdk1.8.0_181文件夹。

(2) . 配置环境变量

使用vi命令编辑profile文件即可。如下

vi /etc/profile

下拉直文件底部,然后添加如下内容

JAVA_HOME=/user/java/jdk1.8.0_181
PATH=$JAVA_HOME/bin:$PATH
CLASSPATH=.:$JAVA_HOME/jre/lib/ext:$JAVA_HOME/lib/tools.jar
export PATH JAVA_HOME CLASSPATH

然后保存退出。为验证是否安装成功,可输入两个命令 javac,java -version。在输入javac出现如下信息,而不是出现command not found

[root@centos1 java]# javac
用法: javac  
其中, 可能的选项包括:
  -g                         生成所有调试信息
  -g:none                    不生成任何调试信息
  -g:{lines,vars,source}     只生成某些调试信息
  -nowarn                    不生成任何警告
  -verbose                   输出有关编译器正在执行的操作的消息
  -deprecation               输出使用已过时的 API 的源位置
  -classpath <路径>            指定查找用户类文件和注释处理程序的位置
  -cp <路径>                   指定查找用户类文件和注释处理程序的位置
  -sourcepath <路径>           指定查找输入源文件的位置
  -bootclasspath <路径>        覆盖引导类文件的位置
  -extdirs <目录>              覆盖所安装扩展的位置
  -endorseddirs <目录>         覆盖签名的标准路径的位置
  -proc:{none,only}          控制是否执行注释处理和/或编译。
  -processor [,,...] 要运行的注释处理程序的名称; 绕过默认的搜索进程
  -processorpath <路径>        指定查找注释处理程序的位置
  -parameters                生成元数据以用于方法参数的反射
  -d <目录>                    指定放置生成的类文件的位置
  -s <目录>                    指定放置生成的源文件的位置
  -h <目录>                    指定放置生成的本机标头文件的位置
  -implicit:{none,class}     指定是否为隐式引用文件生成类文件
  -encoding <编码>             指定源文件使用的字符编码
  -source <发行版>              提供与指定发行版的源兼容性
  -target <发行版>              生成特定 VM 版本的类文件
  -profile <配置文件>            请确保使用的 API 在指定的配置文件中可用
  -version                   版本信息
  -help                      输出标准选项的提要
  -A关键字[=值]                  传递给注释处理程序的选项
  -X                         输出非标准选项的提要
  -J<标记>                     直接将 <标记> 传递给运行时系统
  -Werror                    出现警告时终止编译
  @<文件名>                     从文件读取选项和文件名

然后再输入 java -version 出现如下信息则表示jdk已安装成功

[root@centos1 java]# java -version
java version "1.8.0_181"
Java(TM) SE Runtime Environment (build 1.8.0_45-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)

(2) . Zookeeper下载

下载地址:zookeeper 。如下图

选择合适的版本,这里我下载的是3.4.10。点击即可下载

也可在CentOS中通过shell命令下载。命令如下

wget http://mirrors.cnnic.cn/apache/zookeeper/zookeeper-3.4.10/zookeeper-3.4.10.tar.gz

通过如下镜像网址,可选择合适的版本下载

下载完成后将tar包放到 /user/zookeeper下,此目录可自行定义

进入到该目录,解压缩

tar -zxvf zookeeper-3.4.10.tar.gz

再定义两个目录用于存放日志和数据

图中3.3.6是我之前安装的版本。具体命令如下

mkdir zkdata #存放快照日志
mkdir zkdatalog#存放事物日志

(3) . 修改配置文件

进入到zookeeper的解压目录中,找到conf目录,查看

[root@centos1 /]# cd /user/zookeeper/zookeeper-3.3.6/conf
[root@centos1 conf]# ll
-rw-rw-r--. 1 1000 1000  535 7月  29 2012 configuration.xsl
-rw-rw-r--. 1 1000 1000 1698 7月  29 2012 log4j.properties
-rw-r--r--. 1 root root  550 4月  12 23:10 zoo.cfg
-rw-rw-r--. 1 1000 1000  380 7月  29 2012 zoo_sample.cfg

zoo_sample.cfg 这个文件是官方给我们的zookeeper的样板文件,给他复制一份命名为zoo.cfg,zoo.cfg是官方指定的文件命名规则。 这里我已经创建好了。zoo.cfg中配置信息如下

# 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.
dataDir=/user/zookeeper/zkdata
# the port at which the clients will connect
clientPort=2181
# log dir
dataLogDir=/user/zookeeper/zkdatalog
# ip setting
server.1=192.168.31.135:2888:3888
server.2=192.168.31.136:2888:3888
server.3=192.168.31.137:2888:3888

配置文件属性解释

#tickTime:
这个时间是作为 Zookeeper 服务器之间或客户端与服务器之间维持心跳的时间间隔,也就是每个 tickTime 时间就会发送一个心跳。
#initLimit:
这个配置项是用来配置 Zookeeper 接受客户端(这里所说的客户端不是用户连接 Zookeeper 服务器的客户端,而是 Zookeeper 服务器集群中连接到 Leader 的 Follower 服务器)初始化连接时最长能忍受多少个心跳时间间隔数。当已经超过 5个心跳的时间(也就是 tickTime)长度后 Zookeeper 服务器还没有收到客户端的返回信息,那么表明这个客户端连接失败。总的时间长度就是 5*2000=10 秒
#syncLimit:
这个配置项标识 Leader 与Follower 之间发送消息,请求和应答时间长度,最长不能超过多少个 tickTime 的时间长度,总的时间长度就是5*2000=10秒
#dataDir:
快照日志的存储路径
#dataLogDir:
事物日志的存储路径,如果不配置这个那么事物日志会默认存储到dataDir制定的目录,这样会严重影响zk的性能,当zk吞吐量较大的时候,产生的事物日志、快照日志太多
#clientPort:
这个端口就是客户端连接 Zookeeper 服务器的端口,Zookeeper 会监听这个端口,接受客户端的访问请求。修改他的端口改大点
#server.1=192.168.31.135:2888:3888
这个1是服务器的标识也可以是其他的数字, 表示这个是第几号服务器,用来标识服务器,这个标识要写到快照目录下面myid文件里。192.168.31.135为集群里的IP地址,第一个端口是master和slave之间的通信端口,默认是2888,第二个端口是leader选举的端口,集群刚启动的时候选举或者leader挂掉之后进行新的选举的端口默认是3888

这个配置需要在每个zookeeper节点上配置,接下来在每个节点上分别创建myid文件

#server1
echo "1" > /opt/zookeeper/zkdata/myid
#server2
echo "2" > /opt/zookeeper/zkdata/myid
#server3
echo "3" > /opt/zookeeper/zkdata/myid

注意这里的1,2,3一定要和zoo.cfg配置文件中保持一致。

(4) . 日志配置

作为开发人员,日志对于我们来说重要性不言而喻了,一旦出现问题首先就要去查看日志。那么zookeeper的日志配置在哪呢。同样在conf下有个log4j.properties文件。内容如下

[root@centos1 conf]# cat log4j.properties 
#
# ZooKeeper Logging Configuration
#

# Format is " (, )+

# DEFAULT: console appender only
#日志级别
log4j.rootLogger=INFO, CONSOLE

# Example with rolling log file
#log4j.rootLogger=DEBUG, CONSOLE, ROLLINGFILE

# Example with rolling log file and tracing
#log4j.rootLogger=TRACE, CONSOLE, ROLLINGFILE, TRACEFILE

#
# Log INFO level and above messages to the console
#
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.Threshold=INFO
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} - %-5p [%t:%C{1}@%L] - %m%n

#
# Add ROLLINGFILE to rootLogger to get log file output
#    Log DEBUG level and above messages to a log file
log4j.appender.ROLLINGFILE=org.apache.log4j.RollingFileAppender
log4j.appender.ROLLINGFILE.Threshold=DEBUG
log4j.appender.ROLLINGFILE.File=zookeeper.log

# Max log file size of 10MB
log4j.appender.ROLLINGFILE.MaxFileSize=10MB
# uncomment the next line to limit number of backup files
#log4j.appender.ROLLINGFILE.MaxBackupIndex=10

log4j.appender.ROLLINGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.ROLLINGFILE.layout.ConversionPattern=%d{ISO8601} - %-5p [%t:%C{1}@%L] - %m%n


#
# Add TRACEFILE to rootLogger to get log file output
#    Log DEBUG level and above messages to a log file
log4j.appender.TRACEFILE=org.apache.log4j.FileAppender
log4j.appender.TRACEFILE.Threshold=TRACE
log4j.appender.TRACEFILE.File=zookeeper_trace.log

log4j.appender.TRACEFILE.layout=org.apache.log4j.PatternLayout
### Notice we are including log4j's NDC here (%x)
log4j.appender.TRACEFILE.layout.ConversionPattern=%d{ISO8601} - %-5p [%t:%C{1}@%L][%x] - %m%n

我们写代码时往往也会配置log4j ,因此会与zookeeper共用log4j的配置文件。所以需要修改这个配置文件,如下

# Define some default values that can be overridden by system properties
zookeeper.root.logger=INFO, CONSOLE  #日志级别
zookeeper.console.threshold=INFO  #使用下面的console来打印日志
zookeeper.log.dir=.    #日志打印到哪里,就是在zoo.cfg中配置的路径
zookeeper.log.file=zookeeper.log
zookeeper.log.threshold=DEBUG
zookeeper.tracelog.dir=.
zookeeper.tracelog.file=zookeeper_trace.log
#
# ZooKeeper Logging Configuration
#

# Format is " (, )+

# DEFAULT: console appender only
#日志级别
#log4j.rootLogger=INFO, CONSOLE
log4j.rootLogger=${zookeeper.root.logger}

# Example with rolling log file
#log4j.rootLogger=DEBUG, CONSOLE, ROLLINGFILE

# Example with rolling log file and tracing
#log4j.rootLogger=TRACE, CONSOLE, ROLLINGFILE, TRACEFILE

#
# Log INFO level and above messages to the console
#
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.Threshold=INFO
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} - %-5p [%t:%C{1}@%L] - %m%n

#
# Add ROLLINGFILE to rootLogger to get log file output
#    Log DEBUG level and above messages to a log file
log4j.appender.ROLLINGFILE=org.apache.log4j.RollingFileAppender
log4j.appender.ROLLINGFILE.Threshold=DEBUG
log4j.appender.ROLLINGFILE.File=zookeeper.log

# Max log file size of 10MB
log4j.appender.ROLLINGFILE.MaxFileSize=10MB
# uncomment the next line to limit number of backup files
#log4j.appender.ROLLINGFILE.MaxBackupIndex=10

log4j.appender.ROLLINGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.ROLLINGFILE.layout.ConversionPattern=%d{ISO8601} - %-5p [%t:%C{1}@%L] - %m%n


#
# Add TRACEFILE to rootLogger to get log file output
#    Log DEBUG level and above messages to a log file
log4j.appender.TRACEFILE=org.apache.log4j.FileAppender
log4j.appender.TRACEFILE.Threshold=TRACE
log4j.appender.TRACEFILE.File=zookeeper_trace.log

log4j.appender.TRACEFILE.layout=org.apache.log4j.PatternLayout
### Notice we are including log4j's NDC here (%x)
log4j.appender.TRACEFILE.layout.ConversionPattern=%d{ISO8601} - %-5p [%t:%C{1}@%L][%x] - %m%n

修改完成后,会发现日志文件输出目录不起作用。需修改zkEnv.sh 脚本,如下

[root@centos1 conf]# cat /user/zookeeper/zookeeper-3.3.6/bin/zkEnv.sh
#!/bin/sh

# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License.  You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# This script should be sourced into other zookeeper
# scripts to setup the env variables

# We use ZOOCFGDIR if defined,
# otherwise we use /etc/zookeeper
# or the conf directory that is
# a sibling of this script's directory
if [ "x$ZOOCFGDIR" = "x" ]
then
    if [ -d "/etc/zookeeper" ]
    then
        ZOOCFGDIR="/etc/zookeeper"
    else
        ZOOCFGDIR="$ZOOBINDIR/../conf"
    fi
fi

if [ "x$ZOOCFG" = "x" ]
then
    ZOOCFG="zoo.cfg"
fi

ZOOCFG="$ZOOCFGDIR/$ZOOCFG"

if [ -e "$ZOOCFGDIR/java.env" ]
then
    . "$ZOOCFGDIR/java.env"
fi

if [ "x${ZOO_LOG_DIR}" = "x" ]
then
    ZOO_LOG_DIR="."
fi

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

if [ "$JAVA_HOME" != "" ]; then
  JAVA="$JAVA_HOME/bin/java"
else
  JAVA=java
fi

#add the zoocfg dir to classpath
CLASSPATH="$ZOOCFGDIR:$CLASSPATH"

for i in "$ZOOBINDIR"/../src/java/lib/*.jar
do
    CLASSPATH="$i:$CLASSPATH"
done

#make it work in the release
for i in "$ZOOBINDIR"/../lib/*.jar
do
    CLASSPATH="$i:$CLASSPATH"
done

#make it work in the release
for i in "$ZOOBINDIR"/../zookeeper-*.jar
do
    CLASSPATH="$i:$CLASSPATH"
done

#make it work for developers
for d in "$ZOOBINDIR"/../build/lib/*.jar
do
   CLASSPATH="$d:$CLASSPATH"
done

#make it work for developers
CLASSPATH="$ZOOBINDIR/../build/classes:$CLASSPATH"

case "`uname`" in
    CYGWIN*) cygwin=true ;;
    *) cygwin=false ;;
esac

if $cygwin
then
    CLASSPATH=`cygpath -wp "$CLASSPATH"`
fi

#echo "CLASSPATH=$CLASSPATH"

找到配置ZOO_LOG_DIR以及ZOO_LOG4J_PROP的位置(大概在Line50,Line55) 。修改如下

if [ "x${ZOO_LOG_DIR}" = "x" ]
then
    #配置zookeeper日志输出存放路径
    ZOO_LOG_DIR="/home/xxx/zookeeper-2181/logs"
fi

if [ "x${ZOO_LOG4J_PROP}" = "x" ]
then
    #配置日志输出级别,这里把几个级别一并配上
    ZOO_LOG4J_PROP="INFO,CONSOLE,ROLLINGFILE,TRACEFILE"
fi

这样zookeeper的日志配置就完成了。

(5) . 启动Zookeeper

执行如下命令

#进入到Zookeeper的bin目录下
cd /user/zookeeper/zookeeper-3.3.6/bin
#启动服务(3台都需要操作)
./zkServer.sh start

查看服务状态

./zkServer.sh status

通过该命令能看到如下信息则表示zookeeper已经成功启动

#192.168.31.136
[root@centos2 bin]# ./zkServer.sh status
JMX enabled by default
Using config: /user/zookeeper/zookeeper-3.3.6/bin/../conf/zoo.cfg
Mode: leader
#192.168.31.135
[root@centos3 bin]# ./zkServer.sh status
JMX enabled by default
Using config: /user/zookeeper/zookeeper-3.3.6/bin/../conf/zoo.cfg
Mode: follower

(6) . 常见问题

执行 ./zkServer.sh start 命令未出现异常,但是在执行./zkServer.sh status 命令时报

./zkServer.sh status
It is probably not running

可去bin目录吗,执行cat zookeeper.out查看日志

(1) . 错误信息:没有找到主机路由

该错误是没有关闭防火墙导致的,关闭即可。CentOS中防火墙程序主要是firewall和iptables,CentOS7中firewall服务已经默认安装好了,而iptables服务需要安装,CentOS中 iptables通过控制端口来控制服务,而firewalld则是通过控制协议来控制端口 。命令如下:

yum  install  iptabes-services

firewall 相关的操作

#查看防火墙状态
firewall-cmd    --state

#关闭防火墙
systemctl  stop   firewalld.service

#开启防火墙
systemctl  start   firewalld.service

#禁止开机启动启动防火墙
systemctl   disable   firewalld.service

iptables 相关的操作

#开启iptables防火墙
systemctl  start  iptables.service
#重启iptables防火墙
systemctl  restart  iptables.service
#关闭iptables防火墙
systemctl  stop  iptables.service
#查看iptables防火墙状态
systemctl  status  iptables.service

至此zookeeper安装启动全部完成,可以愉快的玩耍了。


Author: 顺坚
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint polocy. If reproduced, please indicate source 顺坚 !
评论
 Previous
CentOS搭建Hadoop集群 CentOS搭建Hadoop集群
Hadoop是一个由Apache基金会所开发的分布式系统基础架构。 Hadoop实现了一个分布式文件系统(Hadoop Distributed File System),简称HDFS。HDFS有高容错性的特点,并且设计用来部署在低廉的(lo
2018-08-11
Next 
VMware中安装CentOS 7 VMware中安装CentOS 7
Linux是一个诞生于网络、成长于网络且成熟于网络的奇特的免费的操作系统,用户可以通过网络或其他途径免费获得 并可以任意修改其源代码,是一个基于POSIX和UNIX的多用户、多任务、支持多线程和多CPU的操作系统。它能运行主要的UNIX工具
2018-08-04
  TOC