ZooKeeper :搭建ZooKeeper集群

本文将介绍如何搭建​​ZooKeeper​​​集群,博主准备搭建由三个​​ZooKeeper​​​节点组成的集群,先需要创建三台虚拟机(​​VirtualBox​​​可以复制虚拟机),系统为​​CentOS7​​​,每台虚拟机配置相同,内存​​2G​​​以及磁盘​​8G​​。如何创建虚拟机请参考这篇博客:

  • ​​VirtualBox安装CentOS7​​

还需要使用​​XShell​​​来连接虚拟机,毕竟在​​VirtualBox​​​上操作虚拟机比较麻烦。先使用​​VirtualBox​​​进入虚拟机,查询该虚拟机的​​IP​​​地址(使用​​ip addr​​​或者​​ifconfig​​​命令),然后使用​​XShell​​来连接它。

  • ​​ip addr命令介绍​​

静态IP地址

为了避免动态分配​​IP​​​地址而造成的麻烦,将每台虚拟机的​​IP​​​地址设置为静态​​IP​​​地址,这样以后使用​​XShell​​​连接虚拟机,就不需要每次使用​​VirtualBox​​​进入虚拟机查询新分配的​​IP​​地址了。

cd /etc/sysconfig/network-scripts/

ZooKeeper :搭建ZooKeeper集群_zookeeper

该配置文件对应虚拟机的网卡名,如下图所示:

ZooKeeper :搭建ZooKeeper集群_zookeeper_02

先在虚拟机中安装​​vim​​,用来编辑这些配置文件:

yum install -y vim

修改配置文件,设置静态​​IP​​地址:

vim ifcfg-enp0s3

ZooKeeper :搭建ZooKeeper集群_ip地址_03

BOOTPROTO="static"     # 静态IP地址,默认为动态分配
ONBOOT="yes" # 是否开机启用
IPADDR=192.168.1.201 # 设置的静态IP地址
NETMASK=255.255.255.0 # 子网掩码
GATEWAY=192.168.1.1 # 网关
DNS1=192.168.1.1 # DNS服务器

​IP​​​地址就设置成使用​​VirtualBox​​​进入虚拟机查询到的​​IP​​​地址,子网掩码一般都是​​24​​​位(​​255.255.255.0​​​,和本地电脑是一样的),为了简单,将​​GATEWAY​​​和​​DNS​​​设置成本地电脑(​​Windows10​​)的网关即可:

ipconfig

ZooKeeper :搭建ZooKeeper集群_java_04


将三台虚拟机都设置静态​​IP​​​地址之后,就可以将​​VirtualBox​​​上的虚拟机关闭,再使用无界面启动方式启动这些虚拟机,然后使用​​XShell​​连接即可。

搭建ZooKeeper集群

博主将用​​shell​​​脚本来搭建​​ZooKeeper​​​集群(脚本的流程使用​​echo​​命令进行了说明):

#!/bin/bash

# author: itkaven
# input: zookeeper_version ip1 ip2 ip3 quorum_port leader_election_port client_port my_id

# 工具包存放路径
path="/usr/local"

# JDK解压后的目录名、压缩包名
jdk_work="jdk1.8.0_202"
jdk_file="jdk-8u202-linux-x64.tar.gz"

# Zookeeper版本号、解压后的目录名、压缩包名、数据存储路径、日志存储路径、客户端连接端口
zookeeper_version="$1"
zookeeper_work="apache-zookeeper-$zookeeper_version-bin"
zookeeper_file="$zookeeper_work.tar.gz"
data_dir="$path/$zookeeper_work/data"
log_dir="$path/$zookeeper_work/log"

# zookeeper集群的ip地址、quorum端口、leader选举端口、客户端连接端口以及该虚拟机在zookeeper集群中的id
ip1="$2"
ip2="$3"
ip3="$4"
quorum_port="$5"
leader_election_port="$6"
client_port="$7"
my_id="$8"
cluster=("server.1=$ip1:$quorum_port:$leader_election_port"
"server.2=$ip2:$quorum_port:$leader_election_port"
"server.3=$ip3:$quorum_port:$leader_election_port")

install_jdk() {
if [ ! -e "$path/$jdk_work" ]; then
echo "没有安装JDK,准备安装JDK($jdk_work)!"
if [ ! -e "$path/$jdk_file" ]; then
echo "请上传JDK压缩包($jdk_file)!"
else
echo "JDK压缩包($jdk_file)已经上传!"
echo "开始解压!"
tar -zxvf "$path/$jdk_file" -C "$path"
echo "删除压缩包!"
rm -f "$path/$jdk_file"
echo "配置JDK环境变量!"
echo "export JAVA_HOME=$path/$jdk_work" >> /etc/profile
source /etc/profile
echo "export CLASSPATH=.:$JAVA_HOME/lib/" >> /etc/profile
echo "export PATH=$JAVA_HOME/bin:$PATH" >> /etc/profile
source /etc/profile
fi
else
echo "已经安装JDK($jdk_work)!"
fi
}

download_zookeeper() {
if [ -e "$path/$zookeeper_work" ]; then
echo "Zookeeper压缩包已经存在!"
else
echo "Zookeeper压缩包不存在,等待下载!"
yum install -y wget
wget -P "$path" --no-check-certificate "https://downloads.apache.org/zookeeper/zookeeper-$zookeeper_version/$zookeeper_file"
echo "Zookeeper压缩包下载完成!"
echo "开始解压Zookeeper压缩包!"
tar -zxvf "$path/$zookeeper_file" -C "$path"
echo "删除Zookeeper压缩包!"
rm -f "$path/$zookeeper_file"
fi
}

config_and_run_zookeeper() {
# shellcheck disable=SC2164
cd "$path/$zookeeper_work/conf"
echo "copy配置文件(zoo_sample.cfg -> zoo.cfg)!"
cp "zoo_sample.cfg" "zoo.cfg"
echo "修改zoo.cfg配置文件(dataDir=$data_dir clientPort=$client_port dataLogDir=$log_dir)!"
sed -i "s#dataDir=.*#dataDir=$data_dir#g" "zoo.cfg"
sed -i "s#clientPort=.*#clientPort=$client_port#g" "zoo.cfg"
echo "dataLogDir=$log_dir" >> "zoo.cfg"
echo "创建文件夹($data_dir $log_dir)!"
mkdir "$data_dir" "$log_dir"
echo "添加可以使用TTL节点的配置!"
echo "extendedTypesEnabled=true" >> "zoo.cfg"
echo "添加zookeeper集群配置!"
# shellcheck disable=SC2068
for config in ${cluster[@]} ; do
echo "$config" >> "zoo.cfg"
done
echo "$my_id" > "$data_dir/myid"
echo "为了方便,关闭防火墙!"
systemctl stop firewalld
echo "启动Zookeeper!"
# shellcheck disable=SC2164
cd "$path/$zookeeper_work/bin"
./zkServer.sh start
}

if [ $# -ne "8" ]; then
echo "请输入Zookeeper版本号、三台虚拟机的IP地址、quorum端口、leader选举端口、客户端连接端口以及该虚拟机在Zookeeper集群中的id!"
else
install_jdk
download_zookeeper
config_and_run_zookeeper
fi

脚本的意图:

  • 安装​​JDK​​​,需要提前将​​JDK​​​压缩包放到虚拟机的​​/usr/local/​​​路径下,博主不喜欢使用​​yum​​​安装​​JDK​​​,但使用​​wget​​​命令下载​​JDK​​​压缩包得到的是缺损包,因为​​Oracle​​​官方有验证;所以博主采取了折中的方式,手动上传​​JDK​​压缩包,文件解压和配置环境变量就通过脚本完成。
  • 下载​​ZooKeeper​​​(从​​ZooKeeper​​官网),再进行解压。
  • 配置与运行​​ZooKeeper​​​,创建配置文件​​zoo.cfg​​​(通过​​copy​​​官方给的样例配置文件​​zoo_sample.cfg​​​),在配置文件​​zoo.cfg​​​中修改数据存储路径、日志存储路径以及客户端连接端口这三个配置,以及添加可以使用​​TTL​​​节点的配置(​​extendedTypesEnabled=true​​​)和​​ZooKeeper​​​集群配置(​​server.id=ip:quorum_port:leader_election_port​​​),最后创建​​myid​​​文件(在​​dataDir​​​数据存储路径下),内容为该虚拟机在​​ZooKeeper​​​集群中的​​id​​​(如果启用了扩展功能,例如​​TTL​​​节点,由于内部限制,​​id​​​必须在​​[1, 254]​​​之间)。关闭防火墙(方便远程连接​​ZooKeeper​​​以及​​ZooKeeper​​​集群的相互通信),之后启动​​ZooKeeper​​。

将下载好的​​JDK​​​压缩包放到每台虚拟机的​​/usr/local/​​路径下:

ZooKeeper :搭建ZooKeeper集群_spring cloud_05


如果​​JDK​​版本和博主不相同,需要修改脚本的这两个变量:

# JDK解压后的目录名、压缩包名
jdk_work="jdk1.8.0_202"
jdk_file="jdk-8u202-linux-x64.tar.gz"

先将该​​shell​​脚本复制到三台虚拟机上。

vim zookeeper.sh

ZooKeeper :搭建ZooKeeper集群_spring cloud_06


保存后再退出:

  • ​​怎么保存退出 vim 编辑​​

修改​​zookeeper.sh​​脚本的权限(不然没有运行权限):

chmod 700 zookeeper.sh

运行​​zookeeper.sh​​脚本:

./zookeeper.sh 3.6.3 192.168.1.199 192.168.1.200 192.168.1.201 2888 3888 9000 1
./zookeeper.sh 3.6.3 192.168.1.199 192.168.1.200 192.168.1.201 2888 3888 9000 2
./zookeeper.sh 3.6.3 192.168.1.199 192.168.1.200 192.168.1.201 2888 3888 9000 3

​3.6.3​​​是​​ZooKeeper​​​的版本号,三个​​IP​​​地址就是三台虚拟机的​​IP​​​地址,​​2888​​​是​​quorum​​​端口,​​3888​​​是​​leader​​​选举端口,​​9000​​​是客户端连接端口,​​1、2、3​​​是虚拟机在​​ZooKeeper​​​集群中的​​id​​。

server.1=192.168.1.199:2888:3888
server.2=192.168.1.200:2888:3888
server.3=192.168.1.201:2888:3888

等待​​zookeeper.sh​​脚本执行完成。

ZooKeeper :搭建ZooKeeper集群_spring cloud_07

​zookeeper.sh​​​脚本执行完成后,配置文件​​zoo.cfg​​会被创建,并且添加指定的配置信息。

ZooKeeper :搭建ZooKeeper集群_ip地址_08


这个​​myid​​​文件里的内容是虚拟机在​​ZooKeeper​​​集群中的​​id​​​,要和配置文件​​zoo.cfg​​​中的集群配置对应(​​server.id=ip:quorum_port:leader_election_port​​​,​​ip​​​和​​id​​要对应)。

ZooKeeper :搭建ZooKeeper集群_zookeeper_09

leader选举

​leader​​​选举的原理以后再介绍,这里只是演示一下​​ZooKeeper​​​集群的​​leader​​​选举,先查看集群中每个​​ZooKeeper​​​节点的状态,现在节点​​1​​​是​​leader​​节点:

ZooKeeper :搭建ZooKeeper集群_后端_10


ZooKeeper :搭建ZooKeeper集群_zookeeper_11

ZooKeeper :搭建ZooKeeper集群_后端_12


当​​ZooKeeper​​​集群的​​leader​​​节点宕机后,​​ZooKeeper​​​集群会进行​​leader​​​选举,选择新的​​leader​​​节点,先在节点​​1​​​上将​​ZooKeeper​​​服务​​stop​​(模拟宕机):

ZooKeeper :搭建ZooKeeper集群_spring cloud_13

ZooKeeper :搭建ZooKeeper集群_后端_14


节点​​3​​​被选举为了​​ZooKeeper​​​集群新的​​leader​​。

ZooKeeper :搭建ZooKeeper集群_后端_15

数据同步

数据同步的原理以后再介绍,这里只是演示一下​​ZooKeeper​​​集群的数据同步,需要提前准备好​​ZooKeeper​​​文件(当然也可以在​​ZooKeeper​​​节点上启动客户端来连接​​ZooKeeper​​集群,这里只是想演示一下远程登陆):

ZooKeeper :搭建ZooKeeper集群_zookeeper_16


先在本地远程连接​​ZooKeeper​​​集群中任意一个节点(节点​​1​​):

zkCli.cmd -timeout 5000 -server 192.168.1.199:9000

创建​​/kaven​​节点:

ZooKeeper :搭建ZooKeeper集群_ip地址_17


再在另外一个​​ZooKeeper​​​集群节点(节点​​3​​​)上查询是否存在​​/kaven​​节点:

ZooKeeper :搭建ZooKeeper集群_zookeeper_18


很显然​​ZooKeeper​​​集群进行了数据同步(保证数据最终一致性),不然节点​​3​​​上不会存在在节点​​1​​​上创建的​​/kaven​​节点。

搭建​​ZooKeeper​​集群就介绍到这里,如果博主有说错的地方或者大家有不同的见解,欢迎大家评论补充。