zookeeper 动态节点增减配置
zookeeper 动态节点增减配置
zookeeper 动态节点配置方法
以 3 台服务器为例,在我的配置下 ip 地址分别为:
- 192.168.1.227
- 192.168.1.185
- 192.168.1.130 以下分别将这 3 台服务器称为:
node0、node1、node2。
本文不介绍 zookeeper 的安装过程,假设已经安装完成。
我的 zookeeper Server 和 Client 脚本位置如下,需要根据实际情况修改:
1
2
3
# zkServer.sh
ZK_SERVER="./third_party/zookeeper/zookeeper-assembly/target/apache-zookeeper-3.10.0-SNAPSHOT-bin/bin/zkServer.sh"
ZK_CLIENT="./third_party/zookeeper/zookeeper-assembly/target/apache-zookeeper-3.10.0-SNAPSHOT-bin/bin/zkCli.sh"
最基础的 单节点 zookeeper 配置
我们从在 node0 启动一个单节点的 zookeeper 服务开始。
首先,我们在 node0 为 zookeeper 创建一个数据目录:
1
mkdir -p ./tmp/zookeeper_test/zookeeper_data
然后在 node0 上创建一个配置文件 zoo.cfg,存储于 ./tmp/zookeeper_test/zoo.cfg,内容如下:
1
2
3
4
5
6
# zookeeper 配置文件
tickTime=2000
dataDir=./tmp/zookeeper_test/zookeeper_data
initLimit=5
syncLimit=2
server.1=192.168.1.227:2888:3888;2188
最后一行表示集群中只有一个节点,并且 zookeeper 的 follower 与 leader 之间使用端口 2888 进行通信,leader 选举使用端口 3888,客户端连接使用端口 2181。
除此以外,还有一个特殊的配置文件,我们要在 ./tmp/zookeeper_test/zookeeper_data 目录下创建一个名为 myid 的文件,内容为 1,表示这是集群中的第一个节点。
1
echo "1" > ./tmp/zookeeper_test/zookeeper_data/myid
现在,我们可以在 node0 上启动 zookeeper 服务了:
1
2
export ZOO_LOG_DIR=./tmp/zookeeper_test/logs
$ZK_SERVER start ./tmp/zookeeper_test/zoo.cfg
注意,$ZK_SERVER 和 $ZK_CLIENT 变量需要根据实际情况修改为 zookeeper 的启动脚本路径,并在执行前确保已经在当前终端中设置了这两个变量。
我们在执行前定义了环境变量 ZOO_LOG_DIR,用于指定 zookeeper 的日志目录。
zookeeper 成功启动如下图:
数据目录下有文件生成
日志目录下也有日志生成
可以通过 client 脚本连接到 zookeeper 服务:
1
$ZK_CLIENT -server 192.168.1.227:2188
客户端连接成功后,可以使用 ls / 命令查看 zookeeper 的根节点,默认情况下只有一个 /zookeeper 节点。
如果要关闭:
1
$ZK_SERVER stop ./tmp/zookeeper_test/zoo.cfg
下面进行动态节点增减配置
首先,我们清空之前的数据
1
2
rm -rf ./tmp
mkdir -p ./tmp/zookeeper_test/zookeeper_data
我们将从只包含 1 个节点的配置开始,逐步扩展到包含3个节点的配置。注意,包含双数节点的配置在实际生产环境中并不推荐使用。
配置单个节点并允许后续动态扩展:
在 node0 上创建一个新的配置文件 ./tmp/zookeeper_test/zoo.cfg,内容如下:
1
2
3
4
5
6
7
8
9
10
11
# zookeeper 配置文件
tickTime=2000
dataDir=./tmp/zookeeper_test/zookeeper_data
initLimit=5
syncLimit=2
# 动态配置文件
dynamicConfigFile=./tmp/zookeeper_test/dynamic.cfg
# 允许进行动态重配置
reconfigEnabled=true
# 允许单节点运行、允许动态扩展
standaloneEnabled=false
注意,与之前的配置不同,这里没有指定 server.1,而是使用了 dynamicConfigFile 指定了一个动态配置文件 dynamic.cfg。
我们在 ./tmp/zookeeper_test/dynamic.cfg 中具体指定集群初始状态的配置:
1
server.1=192.168.1.227:2888:3888;2188
接下来,我们在 ./tmp/zookeeper_test/zookeeper_data 目录下创建一个名为 myid 的文件,内容为 1,表示这是集群中的第一个节点:
1
echo "1" > ./tmp/zookeeper_test/zookeeper_data/myid
现在,配置文件和数据文件的结构如下:
此时还不能直接启动这个节点,我们还需要配置一个超级用户。
假设超级用户的用户名为super,密码为admin,我们在bash中执行:
1
echo -n super:admin | openssl dgst -binary -sha1 | openssl base64
获得输出 xQJmxLMiHGwaqBvst5y6rkB6HQs=,这时密码的哈希值
用以下命令在 node0 上启动 zookeeper 服务:
1
2
3
export ZOO_LOG_DIR=./tmp/zookeeper_test/logs
export SERVER_JVMFLAGS="-Dzookeeper.DigestAuthenticationProvider.superDigest=super:xQJmxLMiHGwaqBvst5y6rkB6HQs="
$ZK_SERVER start ./tmp/zookeeper_test/zoo.cfg
可以看到 zookeeper 成功启动,并且在 ./tmp/zookeeper_test/zookeeper_data 目录下生成了数据文件。
文件变为:
我们可以通过 client 脚本连接到 zookeeper 服务:
1
$ZK_CLIENT -server 192.168.1.227:2188
在动态配置状态下,我们可以在客户端执行以下命令查看当前的集群状态:
1
config
可以看到目前集群只有一个节点。zookeeper 会为不同版本的动态配置文件生成不同的版本号,当前版本为 100000000,这个版本号会随着每次动态配置的变更而增加。观察文件目录可以找到zookeeper 生成的动态配置文件,如下图中高亮部分所示:
这个文件的内容和我们用 config 命令看到的相同。请注意这个文件是自动生成的,不需要手动修改。
1
server.1=192.168.1.227:2888:3888:participant;0.0.0.0:2188
在 node1 上配置并运行新的 zookeeper 节点
现在我们可以动态扩展集群了。假设我们要添加一个新的节点 node1,其 IP 地址为 192.168.1.185
首先,我们登陆到 node1 上,创建一个新的数据目录:
1
2
rm -rf ./tmp
mkdir -p ./tmp/zookeeper_test/zookeeper_data
然后在 node1 上创建一个配置文件 zoo.cfg,存储于 ./tmp/zookeeper_test/zoo.cfg,内容如下:
1
2
3
4
5
6
7
8
9
10
11
# zookeeper 配置文件
tickTime=2000
dataDir=./tmp/zookeeper_test/zookeeper_data
initLimit=5
syncLimit=2
# 动态配置文件
dynamicConfigFile=./tmp/zookeeper_test/dynamic.cfg
# 允许进行动态重配置
reconfigEnabled=true
# 允许单节点运行、允许动态扩展
standaloneEnabled=false
接下来,我们在 ./tmp/zookeeper_test/dynamic.cfg 中添加新的节点配置:
1
2
server.1=192.168.1.227:2888:3888;2188
server.2=192.168.1.185:2888:3888:observer;2188
注意,我们希望 node1 成为集群中的第二个节点,因此我们在 dynamic.cfg 中添加了 server.2 的配置。server.2 将以 observer 的身份加入集群,这意味着它不会参与选举,但可以接收数据更新。这是为了避免新加入的节点被选举为集群的多数节点。
假设现有集群已经存在多个节点,假设这些节点是 A、B、C,当我们想要添加一个新的节点 D 时,我们需要确保在动态配置文件中包含现有节点的配置,并添加新节点的配置。因此新加入的节点 D 的配置应该包含 A、B、C、D 的信息。
然后在 ./tmp/zookeeper_test/zookeeper_data 目录下创建一个名为 myid 的文件,内容为 2,表示这是集群中的第二个节点:
1
echo "2" > ./tmp/zookeeper_test/zookeeper_data/myid
我们启动 node1 上的 zookeeper 服务:
1
2
3
export ZOO_LOG_DIR=./tmp/zookeeper_test/logs
export SERVER_JVMFLAGS="-Dzookeeper.DigestAuthenticationProvider.superDigest=super:xQJmxLMiHGwaqBvst5y6rkB6HQs="
$ZK_SERVER start ./tmp/zookeeper_test/zoo.cfg
在 node1 上启动 zookeeper 成功后,我们可以通过 client 脚本连接到 zookeeper 服务:
1
$ZK_CLIENT -server 192.168.1.185:2188
执行 config 命令查看当前的集群状态:
这时可以看到 node0 虽然主动加入集群,但是目前由于集群还没有主动更新配置,所以 node1 还没有加入到集群中。
在 node0 上更新动态配置
现在我们回到 node0 上,执行以下命令来更新动态配置:
1
$ZK_CLIENT -server 192.168.1.227:2188
执行以下命令来更新动态配置:
1
2
addauth digest super:admin
reconfig -add server.2=192.168.1.185:2888:3888:observer;2188
查看当前的集群状态:
1
config
回到 node1 上验证
在 node1 上执行以下命令查看当前的集群状态:
1
$ZK_CLIENT -server 192.168.1.185:2188
1
config
可以看到,node1 成功加入了集群,并且状态为 observer。
我们可以在node1上执行以下命令,查看当前node1节点的状态,看它加入集群后有没有完成数据同步
1
echo srvr | nc 127.0.0.1 2188
命令返回:
Mode: observer,说明 node1 成功加入集群。节点还在同步阶段,Mode 字段通常会显示 syncing 或 following / synchronization 等字样
再到 node0 上修改权限
我们可以进一步把 node1 的状态改为 participant,使其参与选举:
1
$ZK_CLIENT -server 192.168.1.227:2188
1
2
3
addauth digest super:admin
reconfig -remove 2
reconfig -add server.2=192.168.1.185:2888:3888:participant;2188
这一步完成后,node0 查看状态得到:
node1 查看状态得到:
说明 node0 是当前节点的 leader, node1 是当前节点的 follower。
客户端同时连接到 node0 和 node1
到这里一步,我们已经成功地将 node1 动态加入到 zookeeper 集群中,并且将其状态从 observer 改为了 participant。
我们可以使 zookeeper 客户端同时连接到 node0 和 node1
1
$ZK_CLIENT -server 192.168.1.227:2188,192.168.1.185:2188
在客户端执行 config 命令查看当前的集群状态:
1
config
模拟 node1 的突然崩溃
我们在 node1 杀死 zookeeper 进程:
此时我们如果继续在 node0 上尝试连接到集群,会发现报错
这是因为对于1个2节点的集群,如果有一个节点宕机,剩下的节点无法形成多数派,因此集群会进入不可用状态。
2 个节点的情况下,半数节点是 1 个,因此如果有一个节点宕机,剩下的 1 个节点无法满足大于半数的要求。
此时我们可以在 node0 上查找 tmp/zookeeper_test/zoo.cfg 文件
1
2
3
4
5
6
7
standaloneEnabled=false
dataDir=./tmp/zookeeper_test/zookeeper_data
tickTime=2000
initLimit=5
syncLimit=2
reconfigEnabled=true
dynamicConfigFile=/root/code/FUSE_test/tmp/zookeeper_test/zoo.cfg.dynamic.10000000e
找到当前使用的动态配置文件 /root/code/FUSE_test/tmp/zookeeper_test/zoo.cfg.dynamic.10000000e
我们打开这个文件,内容如下:
1
2
server.1=192.168.1.227:2888:3888:participant;0.0.0.0:2188
server.2=192.168.1.185:2888:3888:participant;0.0.0.0:2188
我们可以看到,server.2 的状态仍然是 participant,但实际上 node1 已经宕机。 我们修改这个文件,将 server.2 移除并保存
然后在 node0 重启 zookeeper 服务:
1
$ZK_SERVER restart ./tmp/zookeeper_test/zoo.cfg
随后单节点的 zookeeper 服务重新启动成功。


















