服务背景

在现代分布式系统中,协调服务对于确保各个组件之间的同步和通信至关重要。Zookeeper 作为一个高效的分布式协调服务,广泛应用于配置管理、服务发现、分布式锁等场景。在企业中,Zookeeper 常用于构建高可用的分布式应用,例如在大数据处理框架 Hadoop、分布式消息队列 Kafka 等中作为核心的协调服务。

Zookeeper 单点部署

什么是 Zookeeper

Zookeeper 是 Apache 基金会开源的一个顶级项目,主要用于分布式集群的协调服务。其应用场景包括配置中心、注册中心、服务发现等。官网地址:Apache ZooKeeper

下载 Zookeeper 软件包

[root@elk91 ~]# wget https://dlcdn.apache.org/zookeeper/zookeeper-3.8.4/apache-zookeeper-3.8.4-bin.tar.gz

解压软件包

[root@elk91 ~]# tar xf apache-zookeeper-3.8.4-bin.tar.gz -C /usr/local/

创建符号链接

[root@elk91 ~]# ln -svf /usr/local/apache-zookeeper-3.8.4-bin /usr/local/zookeeper

添加环境变量

[root@elk91 ~]# cat /etc/profile.d/zk.sh

#!/bin/bash

export JAVA_HOME=/usr/share/elasticsearch/jdk

export ZK_HOME=/usr/local/zookeeper

export PATH=$PATH:$ZK_HOME/bin:$JAVA_HOME/bin

[root@elk91 ~]# source /etc/profile.d/zk.sh

准备配置文件

[root@elk91 ~]# cp /usr/local/zookeeper/conf/zoo{_sample,}.cfg

启动 Zookeeper 服务

[root@elk91 ~]# zkServer.sh start

ZooKeeper JMX enabled by default

Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg

Starting zookeeper ... STARTED

验证 Zookeeper 服务状态

[root@elk91 ~]# zkServer.sh status

ZooKeeper JMX enabled by default

Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg

Client port found: 2181. Client address: localhost. Client SSL: false.

Mode: standalone

链接 Zookeeper 服务

[root@elk91 ~]# zkCli.sh

Connecting to localhost:2181

...

[zk: localhost:2181(CONNECTED) 0]

[zk: localhost:2181(CONNECTED) 0] ls /

[zookeeper]

[zk: localhost:2181(CONNECTED) 1]

测试单点故障

[root@elk91 ~]# zkServer.sh stop

ZooKeeper JMX enabled by default

Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg

Stopping zookeeper ... STOPPED

Zookeeper 集群部署

停止 Zookeeper 的单点模式

[root@elk91 ~]# zkServer.sh stop

ZooKeeper JMX enabled by default

Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg

Stopping zookeeper ... STOPPED

修改配置文件

[root@elk91 ~]# cat > /usr/local/zookeeper/conf/zoo.cfg <

# 定义最小单元的时间范围tick。

tickTime=2000

# 启动时最长等待tick数量。

initLimit=5

# 数据同步时最长等待的tick时间进行响应ACK

syncLimit=2

# 指定数据目录

dataDir=/oldboyedu/data/zk

# 监听端口

clientPort=2181

# 开启四字命令允许所有的节点访问。

4lw.commands.whitelist=*

# server.ID=A:B:C[:D]

# ID:

# zk的唯一编号。

# A:

# zk的主机地址。

# B:

# leader的选举端口,是谁leader角色,就会监听该端口。

# C:

# 数据通信端口。

# D:

# 可选配置,指定角色。

server.91=10.0.0.91:2888:3888

server.92=10.0.0.92:2888:3888

server.93=10.0.0.93:2888:3888

## Metrics Providers

#

# https://prometheus.io Metrics Exporter

#metricsProvider.className=org.apache.zookeeper.metrics.prometheus.PrometheusMetricsProvider

#metricsProvider.httpHost=0.0.0.0

#metricsProvider.httpPort=7000

#metricsProvider.exportJvmInfo=true

EOF

拷贝软件包到集群的其他节点

[root@elk91 ~]# scp -r /usr/local/zookeeper 10.0.0.92:/usr/local/

[root@elk91 ~]# scp -r /usr/local/zookeeper 10.0.0.93:/usr/local/

[root@elk91 ~]# scp /etc/profile.d/zk.sh 10.0.0.92:/etc/profile.d/

[root@elk91 ~]# scp /etc/profile.d/zk.sh 10.0.0.93:/etc/profile.d/

配置免密登录

[root@elk91 ~]# apt -y install expect

[root@elk91 ~]# cat > password_free_login.sh <<'EOF'

#!/bin/bash

# auther: Jason Yin

# 创建密钥对

ssh-keygen -t rsa -P "" -f /root/.ssh/id_rsa -q

# 声明你服务器密码,建议所有节点的密码均一致,否则该脚本需要再次进行优化

export mypasswd=1

# 定义主机列表

elk_list=(10.0.0.91 10.0.0.92 10.0.0.93)

# 配置免密登录,利用expect工具免交互输入

for i in ${elk_list[@]};do

expect -c "

spawn ssh-copy-id -i /root/.ssh/id_rsa.pub root@$i

expect {

\"*yes/no*\" {send \"yes\r\"; exp_continue}

\"*password*\" {send \"$mypasswd\r\"; exp_continue}

}"

done

EOF

[root@elk91 ~]# bash password_free_login.sh

准备 myid 文件

[root@elk91 ~]# for i in `seq 91 93`; do ssh 10.0.0.$i "install -d /oldboyedu/data/zk && echo $i > /oldboyedu/data/zk/myid";done

启动 Zookeeper 集群

[root@elk91 ~]# for i in `seq 91 93`; do ssh 10.0.0.$i "source /etc/profile.d/zk.sh && zkServer.sh start";done

ZooKeeper JMX enabled by default

Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg

Starting zookeeper ... STARTED

ZooKeeper JMX enabled by default

Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg

Starting zookeeper ... STARTED

ZooKeeper JMX enabled by default

Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg

Starting zookeeper ... STARTED

验证 Zookeeper 集群状态

[root@elk91 ~]# for i in `seq 91 93`; do ssh 10.0.0.$i "source /etc/profile.d/zk.sh && zkServer.sh status";done

ZooKeeper JMX enabled by default

Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg

Client port found: 2181. Client address: localhost. Client SSL: false.

Mode: follower

ZooKeeper JMX enabled by default

Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg

Client port found: 2181. Client address: localhost. Client SSL: false.

Mode: leader

ZooKeeper JMX enabled by default

Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg

Client port found: 2181. Client address: localhost. Client SSL: false.

Mode: follower

连接集群测试

[root@elk91 ~]# zkCli.sh -server 10.0.0.91:2181,10.0.0.92:2181,10.0.0.93:2181

Connecting to 10.0.0.91:2181,10.0.0.92:2181,10.0.0.93:2181

...

[zk: 10.0.0.91:2181,10.0.0.92:2181,10.0.0.93:2181(CONNECTED) 0] ls /

[zookeeper]

[zk: 10.0.0.91:2181,10.0.0.92:2181,10.0.0.93:2181(CONNECTED) 1]

验证 Zookeeper 的高可用

停止 Leader 节点

[root@elk92 ~]# zkServer.sh stop

ZooKeeper JMX enabled by default

Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg

Stopping zookeeper ... STOPPED

观察 Leader 变化

[root@elk91 ~]# for i in `seq 91 93`; do ssh 10.0.0.$i "source /etc/profile.d/zk.sh && zkServer.sh status";done

ZooKeeper JMX enabled by default

Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg

Client port found: 2181. Client address: localhost. Client SSL: false.

Mode: follower

ZooKeeper JMX enabled by default

Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg

Client port found: 2181. Client address: localhost. Client SSL: false.

Error contacting service. It is probably not running.

ZooKeeper JMX enabled by default

Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg

Client port found: 2181. Client address: localhost. Client SSL: false.

Mode: leader

常见问题及解决方案

问题一:Zookeeper 服务无法启动

问题描述

在启动 Zookeeper 服务时,出现错误:

Error contacting service. It is probably not running.

问题分析

这可能是由于配置文件错误、环境变量未正确设置或端口被占用等原因导致的。

解决方案

检查配置文件 zoo.cfg 中的配置是否正确,特别是 dataDir、clientPort 等关键配置。

确保环境变量 ZK_HOME 已正确设置,并且 PATH 中包含 Zookeeper 的 bin 目录。

检查端口 2181 是否被其他服务占用,如有必要,修改 clientPort 配置。

检查日志文件 /usr/local/zookeeper/logs/zookeeper.out,查看是否有更多详细的错误信息。

问题二:Zookeeper 集群节点无法正常通信

问题描述

在集群模式下,部分节点无法正常加入集群,日志中可能出现连接超时或通信错误。

问题分析

这可能是由于网络配置问题、防火墙限制或节点间的时钟不同步等原因导致的。

解决方案

检查各节点间的网络连通性,确保节点间可以正常通信。

确保防火墙允许 Zookeeper 所需的端口(2181、2888、3888 等)的通信。

检查各节点的时钟是否同步,时钟差异可能导致通信问题。

检查 zoo.cfg 文件中各节点的配置是否正确,特别是 server.ID 的配置。

问题三:Zookeeper 集群的高可用性不足

问题描述

在停止 Leader 节点后,集群无法正常选举出新的 Leader,导致服务中断。

问题分析

这可能是由于集群节点数量不足,无法满足 Zookeeper 的高可用性要求。

解决方案

根据 Zookeeper 的高可用性原则,集群节点数量应为奇数,且最少需要 3 个节点。如果要容忍 N 台节点故障,则需要准备 2N+1 台服务器。例如,要容忍 1 台节点故障,需要至少 3 台服务器;要容忍 2 台节点故障,需要至少 5 台服务器。

总结

Zookeeper 作为分布式系统的协调服务,在企业中有着广泛的应用。通过合理的配置和管理,可以确保 Zookeeper 集群的稳定运行和高可用性。在部署和使用 Zookeeper 集群时,需要注意网络配置、防火墙设置、节点数量等关键因素,以确保集群的可靠性和性能。