文章目录
- 1、功能简述
- 1.1 服务目标
- 1.2 文件系统 - 树状结构
- 1.3 数据节点Znode类型
- 1.4 变更通知 - Watcher
- 1.4.1 工作机制
- 1.4.1.1 Client注册
- 1.4.1.2 Server处理
- 1.4.1.3 Client回调
- 1.4.2 监听特性
- 1.5 权限控制 - ACL
- 1.5.1 模式 - scheme
- 1.5.2 权限 - Permission
- 1.6 选举机制
- 1.6.1 集群角色
- 1.6.2 选举状态
- 1.6.3 选举比对值
- 1.6.4 选举规则
- 1.6.5 常见选举场景
- 1.6.5.1 集群第一次启动
- 1.6.5.2 集群非第一次启动
- 1.7 数据写入流程
- 1.7.1 写入请求发送到Leader节点
- 1.7.2 写入请求发送到Following节点
- 1.8 服务应用
- 1.8.1 数据发布/订阅
- 1.8.2 负载均衡
- 1.8.3 命名服务
- 1.8.4 分布式协调/通知
- 1.8.5 集群管理
- 1.8.6 分布式锁
- 1.8.7 队列管理
- 2、服务安装
- 2.1 单机部署
- 2.2 伪集群安装
- 2.3 集群操作脚本
- 3、基础操作
- 3.1 zkServer.sh
- 3.2 zkCli.sh
- 3.2.1 客户端连接
- 3.2.2 Znode
- 3.2.2.1 创建
- 3.2.2.2 修改
- 3.2.2.3 删除
- 3.2.2.4 查看
- 3.2.3 Watcher
- 3.2.3.1 目录变化
- 3.2.3.2 数据变化
- 3.2.3.3 永久监听
- 3.2.3.4 删除监听
- 3.2.4 ACL
- 3.2.4.1 get与set
- 3.2.4.2 认证授权
- 3.2.4.3 限制IP地址
- 3.2.4.4 super
- 4、四字命令
- 4.1 环境准备
- 4.2 配置四字命令白名单
- 4.3 操作详解
- 4.3.1 conf
- 4.3.2 cons
- 4.3.3 crst
- 4.3.4 dump
- 4.3.5 envi
- 4.3.6 ruok
- 4.3.7 stat
- 4.3.8 srst
- 4.3.9 wchs
- 4.3.10 mntr
- 5、Python操作ZK
- 5.1 环境准备
- 5.2 常用操作函数
- 5.2.1 ZK连接客户端 - KazooClient
- 5.2.2 连接ZK - start()
- 5.2.3 创建节点 - create()
- 5.2.4 获取路径的子节点列表 - get_children()
- 5.2.5 获取节点的值 - get()
- 5.2.6 修改节点的值 - set()
- 5.2.7 判断节点是否存在 - exists()
- 5.2.8 删除节点 - delete()
- 5.2.9 关闭连接 - stop()
- 5.3 代码操作案例
- 5.3.1 简单的增删改查
- 5.3.2 监听节点 - watch
1、功能简述
Zookeeper(缩写:ZK)是一个开源的分布式协调服务,为分布式应用提供一致性服务的软件,分布式应用可以基 于ZK实现如:数据发布/订阅、负载均衡、命名服务、分布式协调/通知、集群管理、Master选举、分布式锁、分布 式队列等功能。
1.1 服务目标
ZK将简单易用的接口和性能高效、功能稳定的系统提供给客户,封装好复杂出错的关键服务。客户端的读请求可以 被集群中的任意一个机器处理,如果读请求在节点上注册了监视器,这个监听器由所连接的ZK机器处理;对于写请 求,会同时发送给其他ZK机器并且达到一致后,请求返回成功。随着ZK集群机器数量增多,读请求的吞吐会提 高,但写请求的延时会增大。
有序性是ZK非常重要的一个特征,所有的更新都是全局有序的,每个更新都有唯一的一个时间戳,这个时间戳称 为Zxid(Zookeeper Transaction ID)。读请求只会相对于更新有序,因此读请求的返回结果会携带ZK的最新 Zxid。
1.2 文件系统 - 树状结构
ZK提供了一个多层级的节点命名空间(Znode),为保证高吞吐和低延时功能,在内存中维护了这个树状目录结构,这种特性使ZK不能存放大量数据,因此Znode上存储数据上限为1M。 两者区别:与文件系统不同的是这些节点都可以设置相关数据,而文件系统中只有文件节点可以存放数据而目录节点不可。
1.3 数据节点Znode类型
节点数据类型主要分为五类:
- 持久节点 - Persistent:除非手动删除,否则该节点一直存储在ZK上。
- 临时节点 - Ephemeral:生命周期与客户端会话绑定,当客户端失效时(客户端与ZK断开连接不一定会导致 会话失效)其创建的所有临时节点将会被ZK移除。
- 持久顺序节点 - Persistent_sequential:基本特征与持久节点相同,只是增加了顺序属性,节点名称后会追 加一个由父节点维护的自增型数字。
- 临时顺序节点 - Ephemeral_sequential:基本特征与临时节点相同,只是增加了顺序属性,节点名称后会追 加一个由父节点维护的自增型数字。
- 容器节点 - container:当容器节点的最后一个子元素被删除时,该容器节点将会被删除。
1.4 变更通知 - Watcher
ZK允许客户端向服务端的某个Znode注册一个Watcher监听,当服务端的一些指定事件触发了这个Watcher监听, 服务端就会向指定的客户端发送一个事件通知来实现分布式的通知功能,然后客户端根据Watcher通知状态和事件 类型做出业务上的相关改变。
1.4.1 工作机制
具体流程:Client注册 - Server处理 - Client回调
1.4.1.1 Client注册
- 调用getData/getChildren/exist三个API传入Watcher对象;
- 标记请求request,封装Watcher到WatchRegistration;
- 封装成packet对象,服务端发送request;
- 收到服务端响应后,将Watcher注册到ZK WatcherManager中进行管理;
- 请求返回,完成注册。
1.4.1.2 Server处理
-
服务端接收Watcher并存储:接收到客户端请求后判断是否需要注册Watcher,需要注册时将数据节点的节点 路径和ServerCnxn(代表客户端和服务端的一个连接,实现Watcher的process接口,可以看作为一个 Watcher对象)存储在WatcherManager的WatcherTable和Watche2Paths中。
-
Watcher触发:以服务端接收到setData事务请求触发NodeDataChanged事件为例进行说明:
- 封装WatchedEvent:将通知状态SyncConnected、事件类型NodeDataChanged以及节点路径封装成 一个WatchedEvent对象;
- 查询Watcher:从WatchTable中根据节点路径查找Watcher;
- 找到Watcher:提取并从WatchTable和Watche2Paths中删除对应的Watcher(一次性特征);
- 未找到Watcher:客户端未在该数据节点上注册Watcher;
-
调用process方法触发Watcher:通过ServerCnxn对应的TCP连接发送Watcher事件通知。
1.4.1.3 Client回调
客户端SendThread线程接收事件通知,交由EventThread线程回调Watcher,客户端的Watcher机制同样是一次 性的,一旦被触发后该Watcher就失效了。
1.4.2 监听特性
- 一次性:无论是客户端还是服务端,一旦Watcher监听被触发,ZK都会将其从相应的存储中移除,这样的设 计有效减轻了服务端的压力,防止对于更新频繁的节点,服务端会不断向客户端发送事件通知;
- 客户端串行执行:客户端回调Watcher的过程是一个串行同步的过程;
- 轻量级:Watcher的通知非常简单,只会告知客户端发生了事件,并不会说明事件的具体内容;客户端向服务 端注册Watcher的时候,并不会把客户端真实的Watcher对象实体传送到服务端,仅在客户端请求中使用 boolean类型属性进行了标记;
- 最终一致性而非强一致性:客户端与服务端之间通过Socket连接,Watcher event异步发送Watcher的通知事 件可能由于网络延迟或其他原因导致客户端在不同时间监听到事件通知,由于ZK本身提供了ordering guarantee(客户端监听到事件通知后才会感知到Znode发生变化),因此ZK只能保证最终一致性,而非强一 致性;
1.5 权限控制 - ACL
ACL(Access Control List):权限控制,针对节点可以设置相关读写权限,目的为了保障数据安全性。权限 permissions可以指定不同的权限范围以及⻆色。
1.5.1 模式 - scheme
- world:一种特殊的Digest模式,只有一个用户anyone,形式为:world:anyone:[permissions];
- auth:认证登陆,需要注册用户有权限就可以,形式为auth:user:password:[permissions]
- digest:需对密码进行加密方可访问,组合形式为:digest:username:BASE64(SHA1(password)): [permissions],通过addauth digest <username>:<password>后都能操作指定节点的权限;
- Ip:限制ip进行访问,如:ip:192.168.1.1:[permissions];
- super:超级管理员,拥有所有的权限。
1.5.2 权限 - Permission
- 创建 create:允许授权对象在该Znode下创建子节点;
- 删除 delete:允许授权对象在该Znode下删除子节点;
- 读 read:允许授权对象访问该Znode并读取内容或子节点列表等;
- 写 write:允许授权对象在该Znode下进行更新操作;
- 管理 admin:允许授权对象对该Znode进行ACL设置操作。
1.6 选举机制
ZK多为集群环境,选举过程尤为重要。
1.6.1 集群角色
- Leader:事务请求的唯一调度和处理者,保证集群事务处理的顺序性;集群内部各服务的调度者;
- Follower:处理客户端的非事务请求,转发事务请求给Leader;参与事务请求Proposal投票;参与Leader选 举投票;
- Observer:ZK 3.0版本之后引入的⻆色,在不影响集群事务处理能力的基础上提升集群的非事务处理能力; 处理客户端的非事务请求,转发事务请求给Leader;不参与任何形式的投票机制。
1.6.2 选举状态
- Looking:参加Leader选举状态,当服务器处于该状态时,表明当前集群中没有Leader存在;
- Following:当前集群⻆色是Follower;
- Leading:当前集群⻆色是Leader;
- Observing:当前集群⻆色是Observer。
1.6.3 选举比对值
- Sid - 服务器ID:用来唯一标识一台ZK集群中的机器,集群内不可重复且与myid保持一致;
- Zxid - 事务:Zxid是一个事务ID,用来标识一次服务器状态的变更;
- Epoch:每个Leader任期的代号。没有Leader时同一轮投票过程中的逻辑时钟值是相同的。每投完一次票这 个数据就会增加。
1.6.4 选举规则
- ZK集群中只有超过半数以上的服务器启动,集群方可正常工作(低于半数无法选举Leader);
- 在集群正常工作之前,myid较小的服务器需要给myid较大的服务器投票,直到集群选举出Leader后正常工 作;
- 选举出Leader之后,之前的服务器状态由Looking转变为Following,后续加入集群的服务器⻆色均为 Following;
- 若集群没有Leader(非第一次启动),Epoch值较大的服务器当选为Leader;
- Epoch一致时,Zxid较大当选为Leader;
- Epoch与Zxid一致时,Sid较大当选为Leader,Sid必定不重复。
1.6.5 常见选举场景
假设目前有三台服务器组件ZK集群,服务器编号分别是1、2、3。
1.6.5.1 集群第一次启动
- 1号服务器启动,选举开始,首先1号投自己1票(投票结果:1 - 1),由于其他机器尚未启动无法收到投票信 息,此时1号进入Looking状态;
- 2号服务器启动,参加选举,首先2号投自己1票(投票结果:2 - 1、1 - 1)并与1号服务器交换信息,1号服务 器发现2号服务器myid更大,因此1号服务器将自己的票投给2号服务器(投票结果:2 - 2、1 - 0),此时2号 服务器票数为2 > 3/2 超过集群半数机制,因此2号服务器当选为Leader,1号集群修改状态为Following,2号 修改状态为Leading;
- 3号服务器启动,参加选举,首先3号投自己1票(投票结果:2 - 2、1 - 0、3 - 1)并与1、2号服务器交换信 息,3号服务器发现1、2号服务器未处于Looking状态,已无法修改状态,因此3号服务器遵守选举结果,更改 自己状态为Following,选举结束。
1.6.5.2 集群非第一次启动
- 集群正常运行时突然Leader服务器(2号集群)宕机,整个ZK集群将暂停对外服务,重新进入选举阶段;
- 1、3号服务器修改自己状态为Looking,重新进入选举阶段,此时规定1号服务器Zxid=77,Epoch=1, myid=1;3号服务器Zxid=88,Epoch=1,myid=3;
- 1号与3号集群比较Epoch值,相同时继续比较Zxid值,3号大于1号,因此3号机器为新Leader,1号机器为 Follower;
- 若集群Follower宕机,ZK集群仍可支持对外提供服务,只需Leader和另外一台Follower正常工作即可,若该 机器恢复,仍以Follower⻆色加入集群进行工作。
1.7 数据写入流程
ZK集群(三台服务器)角色分为两类:Leader、Following,当客户端分别请求不同角色写入数据时,其操作流程存在区别,下面对这两种场景分别解析。
1.7.1 写入请求发送到Leader节点
步骤如下:
- 客户端将写入请求发送到Leader节点;
- Leader节点写入完成后将写入请求转发到Following节点;
- Following节点写入操作完成回复Leader节点ACK确认机制;
- Leader节点收到Following节点的ACK之后,当完成写入服务器超过总集群数量半数,则Leader节点返回客户端ACK;
- Leader发送写入请求到其他未完成写入的Following节点;
- 其他未完成的Following节点写入操作完成之后回复Leader节点ACK;
- ZK集群完成写入操作。
1.7.2 写入请求发送到Following节点
步骤如下:
- 客户端将写入请求发送到Following节点;
- 收到写入请求的Following节点将请求转发到Leader节点;
- Leader节点写入完成后将写入请求转发到Following节点;
- Following节点写入操作完成回复Leader节点ACK确认机制;
- 当完成写入服务器超过总集群数量半数,Leader节点回复ACK确认机制到转发写入请求的Following节点,然后收到写入请求的Following节点将回复ACK到客户端;
- Leader发送写入请求到其他未完成写入的Following节点;
- 其他未完成的Following节点写入操作完成之后回复Leader节点ACK;
- ZK集群完成写入操作。
1.8 服务应用
通过对ZK中丰富的数据节点进行交叉使用,配合Watcher事件通知机制,可以非常方便的构建一系列分布式应用的 核心功能。
1.8.1 数据发布/订阅
数据发布/订阅系统:动态获取数据/配置信息,实现数据/配置信息的集中式管理和数据的动态更新
数据特征:数据量较小、数据内容在运行时会发生动态更新、集群中各机器共享,配置一致
实现方式:
- 数据存储:将数据/配置信息存储到ZK上的一个数据节点内;
- 数据获取:应用在启动初始化节点从ZK数据节点读取数据,并在该节点上注册一个数据变更Watcher;
- 数据变更:当变更数据时,更新ZK对应节点数据,ZK会将数据变更通知发到各个客户端,客户端接收到通知 后重新读取变更后的数据即可。
1.8.2 负载均衡
通过不同的路径对应不同机器,使用负载均衡算法在父节点下选择对应满足条件的子节点即可。
1.8.3 命名服务
指通过指定名字来获取资源或服务的地址,利用ZK创建一个全局的路径,这个路径就可以作为一个名称指向集群中的机器提供的服务地址或一个远程对象。
1.8.4 分布式协调/通知
对于系统调度来说:操作人员发送通知实际是通过控制台改变某个节点的状态,然后ZK将这些变化发送给注册了这个节点的Watcher的所有客户端。
对于执行情况汇报:每个工作进程都在某个目录下创建一个临时节点,并携带工作的进度数据,这样汇总的进程可以监控目录子节点的变化获得工作进度的实时全局情况。
1.8.5 集群管理
集群管理主要为两点:是否有机器加入、选举Master;
- 是否有机器加入:所有机器约定在父目录下创建临时目录节点,然后Watcher监听父目录节点的子节点变化消 息,一旦有机器离线其创建的临时目录节点被删除,所有其他机器都将收到事件通知;当新机器加入时,创建 新的临时目录节点,因此也会触发Watcher监听,其他机器同时会收到事件通知。
- 选举Master:每次选择编号最小/大的机器作为Master即可。
1.8.6 分布式锁
在集群环境中可能存在多个进程使用某个资源服务,若某一个进程需要使用集群某服务,需要先申请一个锁,该进程获得锁之后会对所需使用的服务保持独占,因此其他进程将无法访问该服务,当拿到锁的进程完成服务使用后将锁释放掉,使得其他进程来获得锁重复以上过程。通过这个机制,集群环境可以保证分布式系统中多个进程能够有序访问临界服务资源,因此这个场景被称之为分布式锁。
当某个进程接收到写入请求后,在/locks节点下创建一个临时顺序节点,判断自己是否为当前节点下最小节点,如果是则获得锁,反之对前一个节点进行监听,当获取锁后进行服务使用,处理完成后删除节点释放锁,下一个节点收到释放通知,重复进行节点最小判断。
分布式锁分为两类:保持独占、控制时序;
- 保持独占:将ZK上的Znode看作是一把锁,通过创建Znode的方式来实现,例如所有客户端都创 建/distribute_lock节点,最终成功创建的那个客户端就拥有这个锁,用完后删除掉这个节点等同于释放掉 锁;
- 控制时序:/distribute_lock已经预先存在,所有客户端在下面创建临时顺序编号的目录节点,和选举Master 过程相同,获取编号最小的获取到锁,用完后删除释放锁即可。
1.8.7 队列管理
- 同步队列:当队员全部存在时队列方可使用,在定义好的目录下创建临时目录节点,监听节点数量是否为所需 数量即可;
- FIFO队列:与分布式锁控制时序场景类似,队员入列时进行编号,出列按照编号排列,在特定目录下创建持 久化顺序节点,创建成功时使用Watcher通知等待的队列,队列删除序列号最小的节点用于消费,此场景下 ZK的Znode用于存储消息,Znode存储的数据就是消息的内容,Sequential序列号是消息编号,按照顺序取 出即可。
2、服务安装
官网下载安装包链接,下载最新版本即可,JDK环境安装参考文章。
点击下载链接或者使用Linux wget命令下载即可。
$ wget <down_pkg_url>
2.1 单机部署
# 解压安装包到指定目录
[root@localhost tar]# tar -xvf apache-zookeeper-3.8.1-bin.tar.gz -C /middleware/
[root@localhost tar]# cd /middleware/
# 创建软链
[root@localhost middleware]# ln -s apache-zookeeper-3.8.1-bin/ zk
[root@localhost middleware]# ll zk/
total 40
drwxr-xr-x 2 501 games 4096 Jan 26 00:31 bin
drwxr-xr-x 2 501 games 4096 Jan 26 00:31 conf
drwxr-xr-x 5 501 games 4096 Jan 26 00:31 docs
drwxr-xr-x 2 root root 4096 Jun 22 16:40 lib
-rw-r--r-- 1 501 games 11358 Jan 26 00:31 LICENSE.txt
-rw-r--r-- 1 501 games 2084 Jan 26 00:31 NOTICE.txt
-rw-r--r-- 1 501 games 2335 Jan 26 00:31 README.md
-rw-r--r-- 1 501 games 3570 Jan 26 00:31 README_packaging.md
[root@localhost middleware]# ll zk/conf/
total 16
-rw-r--r-- 1 501 games 535 Jan 26 00:31 configuration.xsl
-rw-r--r-- 1 501 games 4559 Jan 26 00:31 logback.xml
-rw-r--r-- 1 501 games 1183 Jan 26 00:31 zoo_sample.cfg
[root@localhost middleware]# cp -a zk/conf/zoo_sample.cfg zk/conf/zoo.cfg
[root@localhost middleware]# cat zk/conf/zoo.cfg
tickTime=2000 # ZK服务器之间心跳时间,单位ms
initLimit=10 # 心跳时间间隔时间 = 10x2000ms
syncLimit=5 # 请求与应答最⻓时间限度 = 5x2000ms
dataDir=/middleware/zookeeper # 数据存储目录
clientPort=2181 # 默认服务端口
#maxClientCnxns=60
#autopurge.snapRetainCount=3
#autopurge.purgeInterval=1
#metricsProvider.className=org.apache.zookeeper.metrics.prometheus.PrometheusMetricsProvider
#metricsProvider.httpHost=0.0.0.0
#metricsProvider.httpPort=7000
#metricsProvider.exportJvmInfo=true
# server.myid=IP:Port1:Port2 # myid为服务器编号,集群部署时需要配置到数据存储目录;port1为服务器与集群Leader通信端口,常用2288;Port2为集群Leader宕机后,需重新选举的通信端口选举新Leader,常用3388
# 创建数据存储目录
[root@localhost middleware]# mkdir zk/data
# 开启服务
[root@localhost middleware]# zk/bin/zkServer.sh start zk/conf/zoo.cfg
# 服务验证
[root@localhost middleware]# ps -ef |grep zookeeper |grep -v grep | wc -l
1
注:ZK为什么要复制配置文件为zoo.cfg方可使用?
[root@localhost middleware]# cat zk/bin/zkServer.sh | grep 'zkEnv.sh' -C 3
ZOOBIN="$(dirname "${ZOOBIN}")"
ZOOBINDIR="$(cd "${ZOOBIN}"; pwd)"
if [ -e "$ZOOBIN/../libexec/zkEnv.sh" ]; then
. "$ZOOBINDIR"/../libexec/zkEnv.sh # 调用zkEnv.sh
else
. "$ZOOBINDIR"/zkEnv.sh
fi
# See the following page for extensive details on setting
[root@centos7 conf]# cat ../bin/zkEnv.sh | grep 'zoo.cfg' -C 3
if [ "x$ZOOCFG" = "x" ]
then
ZOOCFG="zoo.cfg" # 调用配置文件名称为zoo.cfg
fi
ZOOCFG="$ZOOCFGDIR/$ZOOCFG"
2.2 伪集群安装
# 解压安装包三次并修改不同名称
[root@master test]# tar -xvf apache-zookeeper-3.8.1-bin.tar.gz -C /zk_cluster/
[root@master zk_cluster]# ll
total 16
drwxr-xr-x 8 redhat redhat 4096 Jun 21 14:10 zk-1
drwxr-xr-x 8 redhat redhat 4096 Jun 21 14:10 zk-2
drwxr-xr-x 8 redhat redhat 4096 Jun 21 14:10 zk-3
[root@master zk_cluster]# echo /zk_cluster/zk-1/conf/zoo.cfg /zk_cluster/zk-2/conf/zoo.cfg /zk_cluster/zk-3/conf/zoo.cfg | xargs -n 1 cp -v /zk_cluster/zk-1/conf/zoo_sample.cfg
# node1
[root@master zk_cluster]# grep -Ev "^#|^$" /zk_cluster/zk-1/conf/zoo.cfg
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/zk_cluster/zk-1/data
clientPort=2181
server.1=localhost:2287:3387
server.2=localhost:2288:3388
server.3=localhost:2289:3389
# node2
[root@master zk_cluster]# grep -Ev "^#|^$" /zk_cluster/zk-2/conf/zoo.cfg
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/zk_cluster/zk-2/data
clientPort=2182
server.1=localhost:2287:3387
server.2=localhost:2288:3388
server.3=localhost:2289:3389
# node3
[root@master zk_cluster]# grep -Ev "^#|^$" /zk_cluster/zk-3/conf/zoo.cfg
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/zk_cluster/zk-3/data
clientPort=2183
server.1=localhost:2287:3387
server.2=localhost:2288:3388
server.3=localhost:2289:3389
# 配置myid给不同目录(三台均执行),node1 - 1;node2 - 2;node3 - 3
[root@master zk_cluster]# mkdir /zk_cluster/zk-1/data
[root@master zk_cluster]# echo 1 > /zk_cluster/zk-1/data/myid
# 使用第三账户启动服务
[root@master zk_cluster]# chown -R redhat:redhat zk-*
2.3 集群操作脚本
[root@master zk_cluster]# cat cluster.sh
#!/bin/bash
zk_list=( `ls -l /zk_cluster/ | grep zk- | awk '{print$9}'` )
for i in ${zk_list[@]};do
case $1 in
start )
su redhat -c "/zk_cluster/$i/bin/zkServer.sh start /zk_cluster/$i/conf/zoo.cfg"
echo -e "\033[32m$i zookeeper service is STARTED!\033[0m"
;;
stop )
su redhat -c "/zk_cluster/$i/bin/zkServer.sh stop"
echo -e "\033[31m$i zookeeper service is STOPPED!\033[0m"
;;
restart )
su redhat -c "/zk_cluster/$i/bin/zkServer.sh restart"
echo -e "\033[32m$i zookeeper service is RESTART finished!\033[0m"
;;
status )
su redhat -c "/zk_cluster/$i/bin/zkServer.sh status"
;;
* )
echo -e "\033[31mInput ERROR,Please input \"start/stop/status!\"\033[0m"
;;
esac
done
# 脚本执行加权
[root@master zk_cluster]# chmod 755 cluster.sh
# 使用脚本启动服务
[root@master zk_cluster]# ./cluster.sh start
# 服务验证
[root@master zk_cluster]# jps
250273 QuorumPeerMain
252420 Jps
250356 QuorumPeerMain
250447 QuorumPeerMain
[root@master zk_cluster]# ps -ef |grep zookeeper |grep -v grep | wc -l
3
3、基础操作
3.1 zkServer.sh
# 查看/停止/重启 服务状态
[root@master zk_cluster]# ./zk-1/bin/zkServer.sh
ZooKeeper JMX enabled by default
Using config: /zk_cluster/zk-1/bin/../conf/zoo.cfg
Usage: ./zk-1/bin/zkServer.sh [--config <conf-dir>] {start|start- foreground|stop|version|restart|status|print-cmd}
3.2 zkCli.sh
3.2.1 客户端连接
# 连接服务
[root@master zk_cluster]# ./zk-1/bin/zkClient.sh # 默认连接本地2181
# 指定连接服务
[root@master zk_cluster]# ./zk-1/bin/zkClient.sh -server <ip>:<port>
# 错误输入会弹出命令帮助指引
[zk: localhost:2181(CONNECTED) 0] help
ZooKeeper -server host:port -client-configuration properties-file cmd args
addWatch [-m mode] path # optional mode is one of [PERSISTENT, PERSISTENT_RECURSIVE] - default is PERSISTENT_RECURSIVE
addauth scheme auth
close
config [-c] [-w] [-s]
connect host:port
create [-s] [-e] [-c] [-t ttl] path [data] [acl]
delete [-v version] path
deleteall path [-b batch size]
delquota [-n|-b|-N|-B] path
get [-s] [-w] path
getAcl [-s] path
getAllChildrenNumber path
getEphemerals path
history
listquota path
ls [-s] [-w] [-R] path
printwatches on|off
quit
reconfig [-s] [-v version] [[-file path] | [-members serverID=host:port1:port2;port3[,...]*]] | [-add serverId=host:port1:port2;port3[,...]]* [-remove serverId[,...]*]
redo cmdno
removewatches path [-c|-d|-a] [-l]
set [-s] [-v version] path data
setAcl [-s] [-v version] [-R] path acl
setquota -n|-b|-N|-B val path
stat [-w] path
sync path
version
whoami
Command not found: Command not found help
3.2.2 Znode
Znode类型可以划分为三类:永久节点、临时节点、容器节点.
3.2.2.1 创建
# 创建永久节点
[zk: localhost:2181(CONNECTED) 1] create
create [-s] [-e] [-c] [-t ttl] path [data] [acl] [zk: localhost:2181(CONNECTED) 0] create /zk test Created /zk
[zk: localhost:2181(CONNECTED) 2] ls /
[zk, zookeeper]
[zk: localhost:2181(CONNECTED) 3] get
get [-s] [-w] path
[zk: localhost:2181(CONNECTED) 4] get /zk
test
[zk: localhost:2181(CONNECTED) 5] stat /zk
cZxid = 0x400000027 # 创建节点的zxid
ctime = Tue Jun 27 14:39:08 CST 2023 # 创建节点的时间
mZxid = 0x400000027 # 节点最后更新的zxid
mtime = Tue Jun 27 14:39:08 CST 2023 # 节点最后更新的时间
pZxid = 0x400000027 # 节点最后更新的子节点zxid
cversion = 0 # 子节点被更改的次数,子节点的变化都会导致该值递增
dataVersion = 0 # 数据被更改的次数,每次数据变化都会导致该值递增
aclVersion = 0 # ACL更改次数,每次ACL的变更都会导致该值递增
ephemeralOwner = 0x0 # 会话ID,0x0则表示是永久节点,其他表示临时节点
dataLength = 4 # 节点数据⻓度
numChildren = 0 # 节点的子节点数量
# 不支持同名节点创建
[zk: localhost:2181(CONNECTED) 6] create /tempper 1
Created /tempper
[zk: localhost:2181(CONNECTED) 7] create /tempper 1
Node already exists: /tempper
# 创建永久顺序节点(节点名称会自动累加定⻓数字)
[zk: localhost:2181(CONNECTED) 8] create -s /zk/seq test
Created /zk/seq0000000000
[zk: localhost:2181(CONNECTED) 9] stat /zk/seq0000000000
cZxid = 0x40000002a
ctime = Tue Jun 27 14:40:39 CST 2023
mZxid = 0x40000002a
mtime = Tue Jun 27 14:40:39 CST 2023
pZxid = 0x40000002a
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 4
numChildren = 0
# 支持同名节点创建 - 分布式锁特点(实际节点名称不同)
[zk: localhost:2181(CONNECTED) 10] create -s /tempperseq 1
Created /tempperseq0000000012
[zk: localhost:2181(CONNECTED) 11] create -s /tempperseq 1
Created /tempperseq0000000013
[zk: localhost:2181(CONNECTED) 12] create -s /tempperseq 1
Created /tempperseq0000000014
# 创建临时节点(临时节点下不可创建子节点)
[zk: localhost:2181(CONNECTED) 13] create -e /zk/temp test3
Created /zk/temp
[zk: localhost:2181(CONNECTED) 14] stat /zk/temp
cZxid = 0x40000002e
ctime = Tue Jun 27 14:41:55 CST 2023
mZxid = 0x40000002e
mtime = Tue Jun 27 14:41:55 CST 2023
pZxid = 0x40000002e
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x100810390610004 # 临时节点标识
dataLength = 5
numChildren = 0
# 不支持同名节点创建
[zk: localhost:2181(CONNECTED) 15] create -e /tempeph 1
Created /tempeph
[zk: localhost:2181(CONNECTED) 16] create -e /tempeph 1
Node already exists: /tempeph
# 不支持子节点创建
[zk: localhost:2181(CONNECTED) 17] create /tempeph/child test
Ephemerals cannot have children: /tempeph/child
[zk: localhost:2181(CONNECTED) 18] create -e /tempeph/child test
Ephemerals cannot have children: /tempeph/child
# 创建临时顺序节点
[zk: localhost:2181(CONNECTED) 19] create -s -e /zk/tempseq test4
Created /zk/tempseq0000000002
[zk: localhost:2181(CONNECTED) 20] stat /zk/tempseq0000000002
cZxid = 0x400000033
ctime = Tue Jun 27 14:44:10 CST 2023
mZxid = 0x400000033
mtime = Tue Jun 27 14:44:10 CST 2023
pZxid = 0x400000033
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x100810390610004
dataLength = 5
numChildren = 0
# 创建同名节点
[zk: localhost:2181(CONNECTED) 21] create -e -s /tempephseq 1
Created /tempephseq0000000016
[zk: localhost:2181(CONNECTED) 22] create -e -s /tempephseq 1
Created /tempephseq0000000017
[zk: localhost:2181(CONNECTED) 23] create -e -s /tempephseq 1
Created /tempephseq0000000018
# 创建容器节点
[zk: localhost:2181(CONNECTED) 24] create -c /temp/container test5
Created /temp/container
[zk: localhost:2181(CONNECTED) 25] stat /temp/container
cZxid = 0x400000049
ctime = Tue Jun 27 17:16:29 CST 2023
mZxid = 0x400000049
mtime = Tue Jun 27 17:16:29 CST 2023
pZxid = 0x400000049
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0 # 容器节点为永久节点
dataLength = 5
numChildren = 0
# 容器节点不支持为临时节点
[zk: localhost:2181(CONNECTED) 24] create -e -c /temp/containereph test6
-c cannot be combined with -s or -e. Containers cannot be ephemeral or sequential.
3.2.2.2 修改
[zk: localhost:2181(CONNECTED) 0] create /zk/change aaa
Created /zk/change
[zk: localhost:2181(CONNECTED) 1] get /zk/change
aaa
[zk: localhost:2181(CONNECTED) 2] stat /zk/change
cZxid = 0x400000041
ctime = Tue Jun 27 14:56:17 CST 2023
mZxid = 0x400000041
mtime = Tue Jun 27 14:56:17 CST 2023
pZxid = 0x400000041
cversion = 0
dataVersion = 0 # 修改数据dataVersion会自增
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 3
numChildren = 0
[zk: localhost:2181(CONNECTED) 3] set
set [-s] [-v version] path data
[zk: localhost:2181(CONNECTED) 4] set /zk/change bbb
[zk: localhost:2181(CONNECTED) 5] stat /zk/change
cZxid = 0x400000041
ctime = Tue Jun 27 14:56:17 CST 2023
mZxid = 0x400000042
mtime = Tue Jun 27 14:56:36 CST 2023
pZxid = 0x400000041
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 3
numChildren = 0
[zk: localhost:2181(CONNECTED) 6] set -v 1 /zk/change ccc # 指定数据版本修改
[zk: localhost:2181(CONNECTED) 7] stat /zk/change
cZxid = 0x400000041
ctime = Tue Jun 27 14:56:17 CST 2023
mZxid = 0x400000043
mtime = Tue Jun 27 14:56:47 CST 2023
pZxid = 0x400000041
cversion = 0
dataVersion = 2
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 3
numChildren = 0
[zk: localhost:2181(CONNECTED) 8] set -v 1 /zk/change ddd version # 若版本匹配错误,则无法修改数据
No is not valid : /zk/change
3.2.2.3 删除
[zk: localhost:2181(CONNECTED) 0] delete # 只能删除没有子节点的节点
delete [-v version] path
[zk: localhost:2181(CONNECTED) 1] deleteall # 删除节点以及所有子节点
deleteall path [-b batch size]
# 删除子节点
[zk: localhost:2181(CONNECTED) 2] delete /zk/temp
# 删除父节点
[zk: localhost:2181(CONNECTED) 3] delete /zk
Node not empty: /zk
[zk: localhost:2181(CONNECTED) 4] deleteall /zk
3.2.2.4 查看
# 客户端版本
[zk: localhost:2181(CONNECTED) 0] version
ZooKeeper CLI version: 3.8.1-74db005175a4ec545697012f9069cb9dcc8cdda7, built on 2023- 01-25 16:31 UTC
# 查看Znode
[zk: localhost:2181(CONNECTED) 1] ls
ls [-s] [-w] [-R] path
[zk: localhost:2181(CONNECTED) 2] ls /zookeeper [config, quota] # 查看子节点
[zk: localhost:2181(CONNECTED) 3] ls -s /zookeeper [config, quota] # 查看子节点与状态信息
cZxid = 0x0
ctime = Thu Jan 01 08:00:00 CST 1970
mZxid = 0x0
mtime = Thu Jan 01 08:00:00 CST 1970
pZxid = 0x0
cversion = -2
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 0
numChildren = 2
[zk: localhost:2181(CONNECTED) 4] ls -R /zookeeper /zookeeper # 递归查询所有子节点
/zookeeper/config
/zookeeper/quota
# 显示最近执行的11条命令的历史记录
[zk: localhost:2181(CONNECTED) 5] history
# 获取节点下的所有子孙节点数量
[zk: localhost:2181(CONNECTED) 6] getAllChildrenNumber /zookeeper
2
# 获取当前客户端创建的所有临时节点
[zk: localhost:2181(CONNECTED) 7] getAllChildrenNumber /zookeeper
2
# 在leader和follower之间同步一个节点的数据(异步执行)
[zk: localhost:2181(CONNECTED) 8] sync
sync path
# 退出
[zk: localhost:2181(CONNECTED) 9] quit
3.2.3 Watcher
3.2.3.1 目录变化
[zk: localhost:2181(CONNECTED) 0] create /watcher
Created /watcher
[zk: localhost:2181(CONNECTED) 1] ls -w /watcher
[]
[zk: localhost:2181(CONNECTED) 2] create /watcher/w1 aaa
WATCHER::
WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/watcher
Created /watcher/w1
[zk: localhost:2181(CONNECTED) 3] create /watcher/w2 aaa
Created /watcher/w2
3.2.3.2 数据变化
[zk: localhost:2181(CONNECTED) 0] get -w /watcher
null
[zk: localhost:2181(CONNECTED) 1] set /watcher bbb
WATCHER::
WatchedEvent state:SyncConnected type:NodeDataChanged path:/watcher
[zk: localhost:2181(CONNECTED) 2] set /watcher ccc
[zk: localhost:2181(CONNECTED) 3] get /watcher
ccc
3.2.3.3 永久监听
[zk: localhost:2181(CONNECTED) 0] addWatch
addWatch [-m mode] path # optional mode is one of [PERSISTENT, PERSISTENT_RECURSIVE] - default is PERSISTENT_RECURSIVE
- PERSISTENT:节点的数据变化以及子节点的变化会触发相应事件,子节点的数据变化不会触发;
[zk: localhost:2181(CONNECTED) 1] addWatch -m PERSISTENT /watcher
[zk: localhost:2181(CONNECTED) 2] set /watcher ddd # 修改节点数据
WATCHER::
WatchedEvent state:SyncConnected type:NodeDataChanged path:/watcher
[zk: localhost:2181(CONNECTED) 3] ls /watcher
[w1, w2]
[zk: localhost:2181(CONNECTED) 4] create /watcher/w3 000 # 创建子节点
WATCHER::
WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/watcher
Created /watcher/w3
[zk: localhost:2181(CONNECTED) 5] set /watcher/w3 111 # 修改子节点数据
[zk: localhost:2181(CONNECTED) 6] set /watcher/w3 222
[zk: localhost:2181(CONNECTED) 7] delete /watcher/w3 # 删除子节点
WATCHER::
WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/watcher
- PERSISTENT_RECURSIVE:节点的数据变化以及所有子节点的目录或者数据变化都会触发相应事件;
[zk: localhost:2181(CONNECTED) 8] addWatch -m PERSISTENT_RECURSIVE /watcher
[zk: localhost:2181(CONNECTED) 9] ls /watcher
[w1, w2]
[zk: localhost:2181(CONNECTED) 10] create /watcher/w4 000
WATCHER::
WatchedEvent state:SyncConnected type:NodeCreated path:/watcher/w4
Created /watcher/w4
[zk: localhost:2181(CONNECTED) 11] set /watcher/w4 111
WATCHER::
WatchedEvent state:SyncConnected type:NodeDataChanged path:/watcher/w4
[zk: localhost:2181(CONNECTED) 12] create /watcher/w4/w41 000
WATCHER::
WatchedEvent state:SyncConnected type:NodeCreated path:/watcher/w4/w41
Created /watcher/w4/w41
[zk: localhost:2181(CONNECTED) 13] set /watcher/w4/w41 111
WATCHER::
WatchedEvent state:SyncConnected type:NodeDataChanged path:/watcher/w4/w41
[zk: localhost:2181(CONNECTED) 14] del
delete deleteall delquota
[zk: localhost:2181(CONNECTED) 15] deleteall /watcher/w4
WATCHER::
WatchedEvent state:SyncConnected type:NodeDeleted path:/watcher/w4/w41
WATCHER::
WatchedEvent state:SyncConnected type:NodeDeleted path:/watcher/w4
3.2.3.4 删除监听
# 一次性或永久均可删除
[zk: localhost:2181(CONNECTED) 16] removewatches /watcher
WATCHER::
WatchedEvent state:SyncConnected type:PersistentWatchRemoved path:/watcher
3.2.4 ACL
权限构成参考本文1.5章节内容。
3.2.4.1 get与set
# 获取某个节点的权限
[zk: localhost:2181(CONNECTED) 0] create /acl/test1
Created /acl/test1
[zk: localhost:2181(CONNECTED) 1] getAcl /acl/test1
'world,'anyone # 默认权限 world:anyone:cdrwa
: cdrwa
# 设置某个节点的权限
[zk: localhost:2181(CONNECTED) 2] set /acl/test1 world:anyone:crwa [zk: localhost:2181(CONNECTED) 24] getAcl /acl/test1
'world,'anyone
: cdrwa
[zk: localhost:2181(CONNECTED) 3] create /acl/test2 bbb world:anyone:a
Created /acl/test2
3.2.4.2 认证授权
[zk: localhost:2181(CONNECTED) 4] create /acl/test3 ccc auth:admin:123:cdrwa
KeeperErrorCode = InvalidACL for /acl/test3
Acl is not valid : /acl/test3
# 为特定用户添加加密的安全凭证
[zk: localhost:2181(CONNECTED) 5] addauth digest admin:123
[zk: localhost:2181(CONNECTED) 6] create /acl/test3 ccc auth:admin:123:cdrwa # 注册使用明文
Created /acl/test3
[zk: localhost:2181(CONNECTED) 7] getAcl /acl/test3 'digest,'admin:FZZqUdRiWHFSolvFGs6aTyPWBH4= # 存储使用加密形式
: cdrwa
# 退出重新连接ZK(第一次设置完auth权限后,无法修改用户名和密码,可以修改permissons)
[zk: localhost:2181(CONNECTED) 0] get /acl/test3
Insufficient permission : /acl/test3
[zk: localhost:2181(CONNECTED) 1] create /acl/test3/test31
Insufficient permission : /acl/test3/test31
[zk: localhost:2181(CONNECTED) 2] addauth digest admin:123
[zk: localhost:2181(CONNECTED) 3] get /acl/test3
ccc
[zk: localhost:2181(CONNECTED) 4] create /acl/test3/test31
Created /acl/test3/test31
3.2.4.3 限制IP地址
[zk: localhost:2181(CONNECTED) 5] create /acl/test4 111 ip:127.0.0.1:cdrwa
Created /acl/test4
# 退出重新连接ZK
[zk: localhost:2181(CONNECTED) 0] getAcl /acl/test4
'ip,'127.0.0.1
: cdrwa
[zk: localhost:2181(CONNECTED) 1] create /acl/test5 222 ip:192.168.1.1:cdrwa
Created /acl/test5
# 退出重新连接ZK
[zk: localhost:2181(CONNECTED) 0] getAcl /acl/test5
Insufficient permission : /acl/test5
3.2.4.4 super
# 加密super密码admin
[root@master zk_cluster]# echo -n super:admin | openssl dgst -binary -sha1 | openssl base64
xQJmxLMiHGwaqBvst5y6rkB6HQs=
# 修改ZK服务启动脚本
[root@master zk_cluster]# vim zk-1/bin/zkServer.sh
# 164行添加启动参数 Dzookeeper.DigestAuthenticationProvider.superDiges
nohup "$JAVA" $ZOO_DATADIR_AUTOCREATE "-Dzookeeper.log.dir=${ZOO_LOG_DIR}" "- Dzookeeper.DigestAuthenticationProvider.superDiges t=super:xQJmxLMiHGwaqBvst5y6rkB6HQs="\
# 重启ZK服务后连接
[zk: localhost:2181(CONNECTED) 0] addauth digest super:admin [zk: localhost:2181(CONNECTED) 1] whoami
Auth scheme: User
digest: super
super:
ip: 127.0.0.1
[zk: localhost:2181(CONNECTED) 3] deleteall /acl
4、四字命令
传递四个字母的字符串给ZooKeeper,ZooKeeper会返回一些有用的信息到客户端。
4.1 环境准备
nc - net cat:用于扫描与连接指定端口的一个工具,使用ZK四字命令需要提前安装nc工具包(默认Linux不携带此rpm包)。
[root@master zk_cluster]# yum install nc -y
[root@master zk_cluster]# nc --help
nc: invalid option -- '-'
usage: nc [-46cDdFhklNnrStUuvz] [-C certfile] [-e name] [-H hash] [-I length]
[-i interval] [-K keyfile] [-M ttl] [-m minttl] [-O length]
[-o staplefile] [-P proxy_username] [-p source_port] [-R CAfile]
[-s sourceaddr] [-T keyword] [-V rtable] [-W recvlimit] [-w timeout]
[-X proxy_protocol] [-x proxy_address[:port]] [-Z peercertfile]
[destination] [port]
4.2 配置四字命令白名单
# 集群节点均需要添加 4lw.commands.whitelist=*,*代表所有四字命令
[root@master zk_cluster]# sed -i '$a 4lw.commands.whitelist\=\*' zk-1/conf/zoo.cfg
# 配置文件修改需要重启服务
[root@master zk_cluster]# ./cluster.sh restart
4.3 操作详解
命令格式:echo [commond] | nc [ip] [port]
4.3.1 conf
输出相关服务配置的详细信息。比如端口、zk数据及日志配置路径、最大连接数,session超时时间、serverId等。
[root@master zk_cluster]# echo conf | nc 127.0.0.1 2181
clientPort=2181 # 端口号
secureClientPort=-1
dataDir=/zk_cluster/zk-1/data/version-2 # 数据快照文件目录,默认100000次事务生成一次快照
dataDirSize=1180
dataLogDir=/zk_cluster/zk-1/data/version-2 # 事务日志文件目录
dataLogSize=1180
tickTime=2000
maxClientCnxns=60 # 最大连接数
minSessionTimeout=4000
maxSessionTimeout=40000
clientPortListenBacklog=-1
serverId=1 # 服务器编号
initLimit=10
syncLimit=5
electionAlg=3 # 选举算法
electionPort=3387 # 选举端口
quorumPort=2287 # 数据通信端口
peerType=0 # 是否是观察者
membership:
server.1=localhost:2287:3387:participant
server.2=localhost:2288:3388:participant
server.3=localhost:2289:3389:participant
4.3.2 cons
列出所有连接到这台服务器的客户端连接/会话的详细信息。包括“接受/发送”的包数量、session id 、操作延迟、最 后的操作执行等信息。
[root@master zk_cluster]# echo cons | nc 127.0.0.1 2181
/127.0.0.1:56178[0](queued=0,recved=1,sent=0)
/127.0.0.1:56176[1]
(queued=0,recved=2,sent=2,sid=0x1008be8bbdd0000,lop=GETC,est=1688020751472,to=30000,lcxid=0x1,lzxid=0x900000001,lresp=2348972222,llat=1,minlat=0,avglat=4,maxlat=8)
# ip:ip地址
# port:端口号
# queued:等待被处理的请求数,请求缓存在队列中
# received:收到的包数
# sent:发送的包数
# sid:会话id
# lop:最后的操作 GETD-读取数据 DELE-删除数据 CREA-创建数据 # est:连接时间戳
# to:超时时间
# lcxid:当前会话的操作id
# lzxid:最大事务id
# lresp:最后响应时间戳
# llat:最后/最新 延时
# minlat:最小延时
# maxlat:最大延时
# avglat:平均延时
4.3.3 crst
重置当前这台服务器所有连接/会话的统计信息。
[root@master zk_cluster]# echo crst | nc 127.0.0.1 2181
Connection stats reset.
[root@master zk_cluster]# echo cons | nc 127.0.0.1 2181
/127.0.0.1:56182[0](queued=0,recved=1,sent=0)
/127.0.0.1:56176[1]
(queued=0,recved=1,sent=1,sid=0x1008be8bbdd0000,lop=PING,est=1688020751472,to=30000,lzxid=0x900000001,lresp=2349282458,llat=0,minlat=0,avglat=0,maxlat=0)
4.3.4 dump
列出未经处理的会话和临时节点。
# 创建一个临时节点
[zk: localhost:2181(CONNECTED) 1] create -e /temp/temptest
Created /temp/temptest
[root@master zk_cluster]# echo dump | nc 127.0.0.1 2181
SessionTracker dump:
Global Sessions(1):
0x1008be8bbdd0000 30000ms
ephemeral nodes dump:
Sessions with Ephemerals (1):
0x1008be8bbdd0000: # 会话ID
/temp/temptest # 临时节点路径
Connections dump:
Connections Sets (3)/(2):
0 expire at Thu Jun 29 14:46:41 CST 2023:
1 expire at Thu Jun 29 14:46:51 CST 2023:
ip: /127.0.0.1:56186 sessionId: 0x0
1 expire at Thu Jun 29 14:47:01 CST 2023:
ip: /127.0.0.1:56176 sessionId: 0x1008be8bbdd0000
4.3.5 envi
输出关于服务器的环境详细信息。
[root@master zk_cluster]# echo envi | nc 127.0.0.1 2181
Environment:
zookeeper.version=3.8.1-74db005175a4ec545697012f9069cb9dcc8cdda7, built on 2023-01-25
16:31 UTC
host.name=master
java.version=17.0.6
java.vendor=Tencent
java.home=/middleware/TencentKona-17.0.6.b1
java.class.path=/zk_cluster/zk-1/bin/../zookeeper-server/target/classes:~ # 返回过⻓部分省略
java.library.path=/usr/java/packages/lib:/usr/lib64:/lib64:/lib:/usr/lib
java.io.tmpdir=/tmp
java.compiler=<NA>
os.name=Linux
os.arch=amd64
os.version=5.4.119-1-tlinux4-0008
user.name=redhat
user.home=/home/redhat
user.dir=/zk_cluster
os.memory.free=107MB
os.memory.max=1000MB
os.memory.total=126MB
4.3.6 ruok
测试服务是否处于正确运行状态。如果正常返回"imok",否则返回空。
[root@master zk_cluster]# echo ruok | nc 127.0.0.1 2181
imok
4.3.7 stat
输出服务器的详细信息:接收/发送包数量、连接数、模式(leader/follower)、节点总数、延迟。 所有客户端的 列表。
[root@master zk_cluster]# echo stat | nc 127.0.0.1 2181
Zookeeper version: 3.8.1-74db005175a4ec545697012f9069cb9dcc8cdda7, built on 2023-01-25
16:31 UTC
Clients:
/127.0.0.1:56194[0](queued=0,recved=1,sent=0)
/127.0.0.1:56176[1](queued=0,recved=79,sent=79)
Latency min/avg/max: 0/0.3063/8 # 延时
Received: 120 # 收到的包
Sent: 119 # 发送的包
Connections: 2 # 连接数
Outstanding: 0 # 请求堆积数
Zxid: 0x900000002 # 最大事务ID
Mode: follower # 当前节点集群⻆色
Node count: 15 # 节点数量
4.3.8 srst
重置server状态。
[root@master zk_cluster]# echo srst | nc 127.0.0.1 2181
Server stats reset.
[root@master zk_cluster]# echo stat | nc 127.0.0.1 2181
Zookeeper version: 3.8.1-74db005175a4ec545697012f9069cb9dcc8cdda7, built on 2023-01-25
16:31 UTC
Clients:
/127.0.0.1:56200[0](queued=0,recved=1,sent=0)
/127.0.0.1:56176[1](queued=0,recved=103,sent=103)
Latency min/avg/max: 0/0.0/0
Received: 1
Sent: 1
Connections: 2
Outstanding: 0
Zxid: 0x900000002
Mode: follower
Node count: 15
4.3.9 wchs
列出服务器watches的简洁信息:连接总数、watching节点总数和watches总数。
[root@master zk_cluster]# echo wchs | nc 127.0.0.1 2181
0 connections watching 0 paths
Total watches:0
4.3.10 mntr
列出集群的健康状态。包括“接受/发送”的包数量、操作延迟、当前服务模式(leader/follower)、节点总数、 watch总数、临时节点总数。
[root@master zk_cluster]# echo mntr | nc 127.0.0.1 2181
zk_version 3.8.1-74db005175a4ec545697012f9069cb9dcc8cdda7, built on 2023-01-25 16:31 UTC
zk_server_state follower
zk_peer_state following - broadcast
zk_ephemerals_count 0
zk_avg_latency 0.1204
zk_num_alive_connections 1
zk_outstanding_requests 0
zk_znode_count 14
zk_global_sessions 0
zk_non_mtls_remote_conn_count 0
zk_last_client_response_size 16
zk_packets_sent 745
zk_packets_received 743
zk_max_client_response_size 135
zk_connection_drop_probability 0.0
zk_watch_count 0
zk_auth_failed_count 0
zk_min_latency 0
zk_max_file_descriptor_count 1000000
zk_approximate_data_size 315
zk_open_file_descriptor_count 61
zk_local_sessions 0
zk_uptime 11374759
zk_max_latency 3
zk_outstanding_tls_handshake 0
zk_min_client_response_size 16
zk_non_mtls_local_conn_count 0
zk_quorum_size 3
zk_proposal_count 0
zk_watch_bytes 0
zk_outstanding_changes_removed 0
zk_throttled_ops 0
zk_stale_requests_dropped 0
zk_large_requests_rejected 0
zk_insecure_admin_count 0
zk_connection_rejected 0
zk_cnxn_closed_without_zk_server_running 0
zk_sessionless_connections_expired 0
zk_looking_count 0
zk_dead_watchers_queued 0
zk_stale_requests 0
zk_connection_drop_count 0
zk_learner_proposal_received_count 3
zk_digest_mismatches_count 0
zk_dead_watchers_cleared 0
zk_response_packet_cache_hits 0
zk_bytes_received_count 8946
zk_add_dead_watcher_stall_time 0
zk_request_throttle_wait_count 0
zk_requests_not_forwarded_to_commit_processor 0
zk_response_packet_cache_misses 0
zk_ensemble_auth_success 0
zk_prep_processor_request_queued 0
zk_learner_commit_received_count 3
zk_stale_replies 0
zk_connection_request_count 1
zk_response_bytes 207
zk_ensemble_auth_fail 0
zk_diff_count 0
zk_response_packet_get_children_cache_misses 0
zk_connection_revalidate_count 0
zk_quit_leading_due_to_disloyal_voter 0
zk_snap_count 0
zk_unrecoverable_error_count 0
zk_unsuccessful_handshake 0
zk_commit_count 0
zk_stale_sessions_expired 0
zk_response_packet_get_children_cache_hits 0
zk_sync_processor_request_queued 3
zk_outstanding_changes_queued 0
zk_request_commit_queued 3
zk_ensemble_auth_skip 0
zk_skip_learner_request_to_next_processor_count 0
zk_tls_handshake_exceeded 0
zk_revalidate_count 0
zk_avg_socket_closing_time 0.0
zk_min_socket_closing_time 0
zk_max_socket_closing_time 0
zk_cnt_socket_closing_time 0
zk_sum_socket_closing_time 0
zk_avg_proposal_process_time 0.0
zk_min_proposal_process_time 0
zk_max_proposal_process_time 0
zk_cnt_proposal_process_time 0
zk_sum_proposal_process_time 0
zk_avg_leader_unavailable_time 0.0
zk_min_leader_unavailable_time 0
zk_max_leader_unavailable_time 0
zk_cnt_leader_unavailable_time 0
zk_sum_leader_unavailable_time 0
zk_avg_node_created_watch_count 0.0
zk_min_node_created_watch_count 0
zk_max_node_created_watch_count 0
zk_cnt_node_created_watch_count 0
zk_sum_node_created_watch_count 0
zk_avg_session_queues_drained 1.0
zk_min_session_queues_drained 1
zk_max_session_queues_drained 1
zk_cnt_session_queues_drained 3
zk_sum_session_queues_drained 3
zk_avg_write_commit_proc_req_queued 0.0081
zk_min_write_commit_proc_req_queued 0
zk_max_write_commit_proc_req_queued 1
zk_cnt_write_commit_proc_req_queued 742
zk_sum_write_commit_proc_req_queued 6
zk_avg_connection_token_deficit 0.0
zk_min_connection_token_deficit 0
zk_max_connection_token_deficit 0
zk_cnt_connection_token_deficit 1
zk_sum_connection_token_deficit 0
zk_avg_read_commit_proc_req_queued 0.9919
zk_min_read_commit_proc_req_queued 0
zk_max_read_commit_proc_req_queued 1
zk_cnt_read_commit_proc_req_queued 742
zk_sum_read_commit_proc_req_queued 736
zk_avg_node_deleted_watch_count 0.0
zk_min_node_deleted_watch_count 0
zk_max_node_deleted_watch_count 0
zk_cnt_node_deleted_watch_count 0
zk_sum_node_deleted_watch_count 0
zk_avg_startup_txns_load_time 0.0
zk_min_startup_txns_load_time 0
zk_max_startup_txns_load_time 0
zk_cnt_startup_txns_load_time 0
zk_sum_startup_txns_load_time 0
zk_avg_sync_processor_queue_size 0.0
zk_min_sync_processor_queue_size 0
zk_max_sync_processor_queue_size 0
zk_cnt_sync_processor_queue_size 3
zk_sum_sync_processor_queue_size 0
zk_avg_follower_sync_time 0.0
zk_min_follower_sync_time 0
zk_max_follower_sync_time 0
zk_cnt_follower_sync_time 0
zk_sum_follower_sync_time 0
zk_avg_prep_processor_queue_size 0.0
zk_min_prep_processor_queue_size 0
zk_max_prep_processor_queue_size 0
zk_cnt_prep_processor_queue_size 0
zk_sum_prep_processor_queue_size 0
zk_avg_fsynctime 1.6667
zk_min_fsynctime 1
zk_max_fsynctime 2
zk_cnt_fsynctime 3
zk_sum_fsynctime 5
zk_avg_inflight_snap_count 0.0
zk_min_inflight_snap_count 0
zk_max_inflight_snap_count 0
zk_cnt_inflight_snap_count 0
zk_sum_inflight_snap_count 0
zk_avg_reads_issued_from_session_queue 0.0
zk_min_reads_issued_from_session_queue 0
zk_max_reads_issued_from_session_queue 0
zk_cnt_reads_issued_from_session_queue 3
zk_sum_reads_issued_from_session_queue 0
zk_avg_learner_request_processor_queue_size 0.0
zk_min_learner_request_processor_queue_size 0
zk_max_learner_request_processor_queue_size 0
zk_cnt_learner_request_processor_queue_size 739
zk_sum_learner_request_processor_queue_size 0
zk_avg_snapshottime 0.0
zk_min_snapshottime 0
zk_max_snapshottime 0
zk_cnt_snapshottime 0
zk_sum_snapshottime 0
zk_avg_unavailable_time 0.0
zk_min_unavailable_time 0
zk_max_unavailable_time 0
zk_cnt_unavailable_time 0
zk_sum_unavailable_time 0
zk_avg_startup_txns_loaded 0.0
zk_min_startup_txns_loaded 0
zk_max_startup_txns_loaded 0
zk_cnt_startup_txns_loaded 0
zk_sum_startup_txns_loaded 0
zk_avg_reads_after_write_in_session_queue 0.0
zk_min_reads_after_write_in_session_queue 0
zk_max_reads_after_write_in_session_queue 0
zk_cnt_reads_after_write_in_session_queue 3
zk_sum_reads_after_write_in_session_queue 0
zk_avg_requests_in_session_queue 1.0
zk_min_requests_in_session_queue 1
zk_max_requests_in_session_queue 1
zk_cnt_requests_in_session_queue 6
zk_sum_requests_in_session_queue 6
zk_avg_write_commit_proc_issued 1.0
zk_min_write_commit_proc_issued 1
zk_max_write_commit_proc_issued 1
zk_cnt_write_commit_proc_issued 3
zk_sum_write_commit_proc_issued 3
zk_avg_prep_process_time 0.0
zk_min_prep_process_time 0
zk_max_prep_process_time 0
zk_cnt_prep_process_time 0
zk_sum_prep_process_time 0
zk_avg_pending_session_queue_size 1.0
zk_min_pending_session_queue_size 1
zk_max_pending_session_queue_size 1
zk_cnt_pending_session_queue_size 3
zk_sum_pending_session_queue_size 3
zk_avg_time_waiting_empty_pool_in_commit_processor_read_ms 0.0
zk_min_time_waiting_empty_pool_in_commit_processor_read_ms 0
zk_max_time_waiting_empty_pool_in_commit_processor_read_ms 0
zk_cnt_time_waiting_empty_pool_in_commit_processor_read_ms 3
zk_sum_time_waiting_empty_pool_in_commit_processor_read_ms 0
zk_avg_commit_process_time 0.0148
zk_min_commit_process_time 0
zk_max_commit_process_time 1
zk_cnt_commit_process_time 742
zk_sum_commit_process_time 11
zk_avg_dbinittime 0.0
zk_min_dbinittime 0
zk_max_dbinittime 0
zk_cnt_dbinittime 0
zk_sum_dbinittime 0
zk_avg_inflight_diff_count 0.0
zk_min_inflight_diff_count 0
zk_max_inflight_diff_count 0
zk_cnt_inflight_diff_count 0
zk_sum_inflight_diff_count 0
zk_avg_netty_queued_buffer_capacity 0.0
zk_min_netty_queued_buffer_capacity 0
zk_max_netty_queued_buffer_capacity 0
zk_cnt_netty_queued_buffer_capacity 0
zk_sum_netty_queued_buffer_capacity 0
zk_avg_election_time 0.0
zk_min_election_time 0
zk_max_election_time 0
zk_cnt_election_time 0
zk_sum_election_time 0
zk_avg_commit_commit_proc_req_queued 0.004
zk_min_commit_commit_proc_req_queued 0
zk_max_commit_commit_proc_req_queued 1
zk_cnt_commit_commit_proc_req_queued 742
zk_sum_commit_commit_proc_req_queued 3
zk_avg_sync_processor_batch_size 1.0
zk_min_sync_processor_batch_size 1
zk_max_sync_processor_batch_size 1
zk_cnt_sync_processor_batch_size 3
zk_sum_sync_processor_batch_size 3
zk_avg_node_children_watch_count 0.0
zk_min_node_children_watch_count 0
zk_max_node_children_watch_count 0
zk_cnt_node_children_watch_count 0
zk_sum_node_children_watch_count 0
zk_avg_write_batch_time_in_commit_processor 0.3333
zk_min_write_batch_time_in_commit_processor 0
zk_max_write_batch_time_in_commit_processor 1
zk_cnt_write_batch_time_in_commit_processor 3
zk_sum_write_batch_time_in_commit_processor 1
zk_avg_read_commit_proc_issued 0.9919
zk_min_read_commit_proc_issued 0
zk_max_read_commit_proc_issued 1
zk_cnt_read_commit_proc_issued 742
zk_sum_read_commit_proc_issued 736
zk_avg_concurrent_request_processing_in_commit_processor 0.0
zk_min_concurrent_request_processing_in_commit_processor 0
zk_max_concurrent_request_processing_in_commit_processor 0
zk_cnt_concurrent_request_processing_in_commit_processor 0
zk_sum_concurrent_request_processing_in_commit_processor 0
zk_avg_observer_sync_time 0.0
zk_min_observer_sync_time 0
zk_max_observer_sync_time 0
zk_cnt_observer_sync_time 0
zk_sum_observer_sync_time 0
zk_avg_node_changed_watch_count 0.0
zk_min_node_changed_watch_count 0
zk_max_node_changed_watch_count 0
zk_cnt_node_changed_watch_count 0
zk_sum_node_changed_watch_count 0
zk_avg_sync_process_time 0.3333
zk_min_sync_process_time 0
zk_max_sync_process_time 1
zk_cnt_sync_process_time 3
zk_sum_sync_process_time 1
zk_avg_startup_snap_load_time 0.0
zk_min_startup_snap_load_time 0
zk_max_startup_snap_load_time 0
zk_cnt_startup_snap_load_time 0
zk_sum_startup_snap_load_time 0
zk_avg_prep_processor_queue_time_ms 0.0
zk_min_prep_processor_queue_time_ms 0
zk_max_prep_processor_queue_time_ms 0
zk_cnt_prep_processor_queue_time_ms 0
zk_sum_prep_processor_queue_time_ms 0
zk_p50_prep_processor_queue_time_ms 0
zk_p95_prep_processor_queue_time_ms 0
zk_p99_prep_processor_queue_time_ms 0
zk_p999_prep_processor_queue_time_ms 0
zk_avg_jvm_pause_time_ms 0.0
zk_min_jvm_pause_time_ms 0
zk_max_jvm_pause_time_ms 0
zk_cnt_jvm_pause_time_ms 0
zk_sum_jvm_pause_time_ms 0
zk_p50_jvm_pause_time_ms 0
zk_p95_jvm_pause_time_ms 0
zk_p99_jvm_pause_time_ms 0
zk_p999_jvm_pause_time_ms 0
zk_avg_close_session_prep_time 0.0
zk_min_close_session_prep_time 0
zk_max_close_session_prep_time 0
zk_cnt_close_session_prep_time 0
zk_sum_close_session_prep_time 0
zk_p50_close_session_prep_time 0
zk_p95_close_session_prep_time 0
zk_p99_close_session_prep_time 0
zk_p999_close_session_prep_time 0
zk_avg_read_commitproc_time_ms 0.0571
zk_min_read_commitproc_time_ms 0
zk_max_read_commitproc_time_ms 1
zk_cnt_read_commitproc_time_ms 736
zk_sum_read_commitproc_time_ms 42
zk_p50_read_commitproc_time_ms 0
zk_p95_read_commitproc_time_ms 1
zk_p99_read_commitproc_time_ms 1
zk_p999_read_commitproc_time_ms 1
zk_avg_updatelatency 2.3333
zk_min_updatelatency 2
zk_max_updatelatency 3
zk_cnt_updatelatency 3
zk_sum_updatelatency 7
zk_p50_updatelatency 2
zk_p95_updatelatency 3
zk_p99_updatelatency 3
zk_p999_updatelatency 3
zk_avg_local_write_committed_time_ms 0.0
zk_min_local_write_committed_time_ms 0
zk_max_local_write_committed_time_ms 0
zk_cnt_local_write_committed_time_ms 3
zk_sum_local_write_committed_time_ms 0
zk_p50_local_write_committed_time_ms 0
zk_p95_local_write_committed_time_ms 0
zk_p99_local_write_committed_time_ms 0
zk_p999_local_write_committed_time_ms 0
zk_avg_request_throttle_queue_time_ms 0.0108
zk_min_request_throttle_queue_time_ms 0
zk_max_request_throttle_queue_time_ms 1
zk_cnt_request_throttle_queue_time_ms 739
zk_sum_request_throttle_queue_time_ms 8
zk_p50_request_throttle_queue_time_ms 0
zk_p95_request_throttle_queue_time_ms 0
zk_p99_request_throttle_queue_time_ms 1
zk_p999_request_throttle_queue_time_ms 1
zk_avg_readlatency 0.1114
zk_min_readlatency 0
zk_max_readlatency 2
zk_cnt_readlatency 736
zk_sum_readlatency 82
zk_p50_readlatency 0
zk_p95_readlatency 1
zk_p99_readlatency 1
zk_p999_readlatency 2
zk_avg_quorum_ack_latency 0.0
zk_min_quorum_ack_latency 0
zk_max_quorum_ack_latency 0
zk_cnt_quorum_ack_latency 0
zk_sum_quorum_ack_latency 0
zk_p50_quorum_ack_latency 0
zk_p95_quorum_ack_latency 0
zk_p99_quorum_ack_latency 0
zk_p999_quorum_ack_latency 0
zk_avg_om_commit_process_time_ms 0.0
zk_min_om_commit_process_time_ms 0
zk_max_om_commit_process_time_ms 0
zk_cnt_om_commit_process_time_ms 0
zk_sum_om_commit_process_time_ms 0
zk_p50_om_commit_process_time_ms 0
zk_p95_om_commit_process_time_ms 0
zk_p99_om_commit_process_time_ms 0
zk_p999_om_commit_process_time_ms 0
zk_avg_read_final_proc_time_ms 0.053
zk_min_read_final_proc_time_ms 0
zk_max_read_final_proc_time_ms 2
zk_cnt_read_final_proc_time_ms 736
zk_sum_read_final_proc_time_ms 39
zk_p50_read_final_proc_time_ms 0
zk_p95_read_final_proc_time_ms 1
zk_p99_read_final_proc_time_ms 1
zk_p999_read_final_proc_time_ms 2
zk_avg_commit_propagation_latency 2.0
zk_min_commit_propagation_latency 1
zk_max_commit_propagation_latency 3
zk_cnt_commit_propagation_latency 3
zk_sum_commit_propagation_latency 6
zk_p50_commit_propagation_latency 2
zk_p95_commit_propagation_latency 3
zk_p99_commit_propagation_latency 3
zk_p999_commit_propagation_latency 3
zk_avg_dead_watchers_cleaner_latency 0.0
zk_min_dead_watchers_cleaner_latency 0
zk_max_dead_watchers_cleaner_latency 0
zk_cnt_dead_watchers_cleaner_latency 0
zk_sum_dead_watchers_cleaner_latency 0
zk_p50_dead_watchers_cleaner_latency 0
zk_p95_dead_watchers_cleaner_latency 0
zk_p99_dead_watchers_cleaner_latency 0
zk_p999_dead_watchers_cleaner_latency 0
zk_avg_write_final_proc_time_ms 0.3333
zk_min_write_final_proc_time_ms 0
zk_max_write_final_proc_time_ms 1
zk_cnt_write_final_proc_time_ms 3
zk_sum_write_final_proc_time_ms 1
zk_p50_write_final_proc_time_ms 0
zk_p95_write_final_proc_time_ms 1
zk_p99_write_final_proc_time_ms 1
zk_p999_write_final_proc_time_ms 1
zk_avg_proposal_ack_creation_latency 3.0
zk_min_proposal_ack_creation_latency 2
zk_max_proposal_ack_creation_latency 4
zk_cnt_proposal_ack_creation_latency 3
zk_sum_proposal_ack_creation_latency 9
zk_p50_proposal_ack_creation_latency 3
zk_p95_proposal_ack_creation_latency 4
zk_p99_proposal_ack_creation_latency 4
zk_p999_proposal_ack_creation_latency 4
zk_avg_proposal_latency 0.6667
zk_min_proposal_latency 0
zk_max_proposal_latency 1
zk_cnt_proposal_latency 3
zk_sum_proposal_latency 2
zk_p50_proposal_latency 1
zk_p95_proposal_latency 1
zk_p99_proposal_latency 1
zk_p999_proposal_latency 1
zk_avg_om_proposal_process_time_ms 0.0
zk_min_om_proposal_process_time_ms 0
zk_max_om_proposal_process_time_ms 0
zk_cnt_om_proposal_process_time_ms 0
zk_sum_om_proposal_process_time_ms 0
zk_p50_om_proposal_process_time_ms 0
zk_p95_om_proposal_process_time_ms 0
zk_p99_om_proposal_process_time_ms 0
zk_p999_om_proposal_process_time_ms 0
zk_avg_sync_processor_queue_and_flush_time_ms 2.3333
zk_min_sync_processor_queue_and_flush_time_ms 1
zk_max_sync_processor_queue_and_flush_time_ms 3
zk_cnt_sync_processor_queue_and_flush_time_ms 3
zk_sum_sync_processor_queue_and_flush_time_ms 7
zk_p50_sync_processor_queue_and_flush_time_ms 3
zk_p95_sync_processor_queue_and_flush_time_ms 3
zk_p99_sync_processor_queue_and_flush_time_ms 3
zk_p999_sync_processor_queue_and_flush_time_ms 3
zk_avg_propagation_latency 2.6667
zk_min_propagation_latency 2
zk_max_propagation_latency 4
zk_cnt_propagation_latency 3
zk_sum_propagation_latency 8
zk_p50_propagation_latency 2
zk_p95_propagation_latency 4
zk_p99_propagation_latency 4
zk_p999_propagation_latency 4
zk_avg_server_write_committed_time_ms 0.0
zk_min_server_write_committed_time_ms 0
zk_max_server_write_committed_time_ms 0
zk_cnt_server_write_committed_time_ms 0
zk_sum_server_write_committed_time_ms 0
zk_p50_server_write_committed_time_ms 0
zk_p95_server_write_committed_time_ms 0
zk_p99_server_write_committed_time_ms 0
zk_p999_server_write_committed_time_ms 0
zk_avg_sync_processor_queue_time_ms 0.0
zk_min_sync_processor_queue_time_ms 0
zk_max_sync_processor_queue_time_ms 0
zk_cnt_sync_processor_queue_time_ms 3
zk_sum_sync_processor_queue_time_ms 0
zk_p50_sync_processor_queue_time_ms 0
zk_p95_sync_processor_queue_time_ms 0
zk_p99_sync_processor_queue_time_ms 0
zk_p999_sync_processor_queue_time_ms 0
zk_avg_sync_processor_queue_flush_time_ms 2.0
zk_min_sync_processor_queue_flush_time_ms 1
zk_max_sync_processor_queue_flush_time_ms 3
zk_cnt_sync_processor_queue_flush_time_ms 3
zk_sum_sync_processor_queue_flush_time_ms 6
zk_p50_sync_processor_queue_flush_time_ms 2
zk_p95_sync_processor_queue_flush_time_ms 3
zk_p99_sync_processor_queue_flush_time_ms 3
zk_p999_sync_processor_queue_flush_time_ms 3
zk_avg_write_commitproc_time_ms 2.3333
zk_min_write_commitproc_time_ms 2
zk_max_write_commitproc_time_ms 3
zk_cnt_write_commitproc_time_ms 3
zk_sum_write_commitproc_time_ms 7
zk_p50_write_commitproc_time_ms 2
zk_p95_write_commitproc_time_ms 3
zk_p99_write_commitproc_time_ms 3
zk_p999_write_commitproc_time_ms 3
zk_avg_watcher_write_per_namespace 0.0
zk_min_watcher_write_per_namespace 0
zk_max_watcher_write_per_namespace 0
zk_cnt_watcher_write_per_namespace 0
zk_sum_watcher_write_per_namespace 0
zk_avg_temp_write_per_namespace 14.0
zk_min_temp_write_per_namespace 14
zk_max_temp_write_per_namespace 14
zk_cnt_temp_write_per_namespace 1
zk_sum_temp_write_per_namespace 14
zk_avg_zookeeper_write_per_namespace 0.0
zk_min_zookeeper_write_per_namespace 0
zk_max_zookeeper_write_per_namespace 0
zk_cnt_zookeeper_write_per_namespace 0
zk_sum_zookeeper_write_per_namespace 0
zk_avg_tempper_write_per_namespace 0.0
zk_min_tempper_write_per_namespace 0
zk_max_tempper_write_per_namespace 0
zk_cnt_tempper_write_per_namespace 0
zk_sum_tempper_write_per_namespace 0
zk_avg_tempeph_write_per_namespace 0.0
zk_min_tempeph_write_per_namespace 0
zk_max_tempeph_write_per_namespace 0
zk_cnt_tempeph_write_per_namespace 0
zk_sum_tempeph_write_per_namespace 0
zk_avg_acl_write_per_namespace 0.0
zk_min_acl_write_per_namespace 0
zk_max_acl_write_per_namespace 0
zk_cnt_acl_write_per_namespace 0
zk_sum_acl_write_per_namespace 0
zk_avg_tempperseq0000000013_write_per_namespace 0.0
zk_min_tempperseq0000000013_write_per_namespace 0
zk_max_tempperseq0000000013_write_per_namespace 0
zk_cnt_tempperseq0000000013_write_per_namespace 0
zk_sum_tempperseq0000000013_write_per_namespace 0
zk_avg_zk_write_per_namespace 0.0
zk_min_zk_write_per_namespace 0
zk_max_zk_write_per_namespace 0
zk_cnt_zk_write_per_namespace 0
zk_sum_zk_write_per_namespace 0
zk_avg_tempperseq0000000014_write_per_namespace 0.0
zk_min_tempperseq0000000014_write_per_namespace 0
zk_max_tempperseq0000000014_write_per_namespace 0
zk_cnt_tempperseq0000000014_write_per_namespace 0
zk_sum_tempperseq0000000014_write_per_namespace 0
zk_avg_temp0000000003_write_per_namespace 0.0
zk_min_temp0000000003_write_per_namespace 0
zk_max_temp0000000003_write_per_namespace 0
zk_cnt_temp0000000003_write_per_namespace 0
zk_sum_temp0000000003_write_per_namespace 0
zk_avg_temp0000000002_write_per_namespace 0.0
zk_min_temp0000000002_write_per_namespace 0
zk_max_temp0000000002_write_per_namespace 0
zk_cnt_temp0000000002_write_per_namespace 0
zk_sum_temp0000000002_write_per_namespace 0
zk_avg_temp0000000001_write_per_namespace 0.0
zk_min_temp0000000001_write_per_namespace 0
zk_max_temp0000000001_write_per_namespace 0
zk_cnt_temp0000000001_write_per_namespace 0
zk_sum_temp0000000001_write_per_namespace 0
zk_avg_temp0000000007_write_per_namespace 0.0
zk_min_temp0000000007_write_per_namespace 0
zk_max_temp0000000007_write_per_namespace 0
zk_cnt_temp0000000007_write_per_namespace 0
zk_sum_temp0000000007_write_per_namespace 0
zk_avg_temp0000000006_write_per_namespace 0.0
zk_min_temp0000000006_write_per_namespace 0
zk_max_temp0000000006_write_per_namespace 0
zk_cnt_temp0000000006_write_per_namespace 0
zk_sum_temp0000000006_write_per_namespace 0
zk_avg_temp0000000005_write_per_namespace 0.0
zk_min_temp0000000005_write_per_namespace 0
zk_max_temp0000000005_write_per_namespace 0
zk_cnt_temp0000000005_write_per_namespace 0
zk_sum_temp0000000005_write_per_namespace 0
zk_avg_tempephseq0000000018_write_per_namespace 0.0
zk_min_tempephseq0000000018_write_per_namespace 0
zk_max_tempephseq0000000018_write_per_namespace 0
zk_cnt_tempephseq0000000018_write_per_namespace 0
zk_sum_tempephseq0000000018_write_per_namespace 0
zk_avg_temp0000000004_write_per_namespace 0.0
zk_min_temp0000000004_write_per_namespace 0
zk_max_temp0000000004_write_per_namespace 0
zk_cnt_temp0000000004_write_per_namespace 0
zk_sum_temp0000000004_write_per_namespace 0
zk_avg_tempephseq0000000017_write_per_namespace 0.0
zk_min_tempephseq0000000017_write_per_namespace 0
zk_max_tempephseq0000000017_write_per_namespace 0
zk_cnt_tempephseq0000000017_write_per_namespace 0
zk_sum_tempephseq0000000017_write_per_namespace 0
zk_avg_tempephseq0000000016_write_per_namespace 0.0
zk_min_tempephseq0000000016_write_per_namespace 0
zk_max_tempephseq0000000016_write_per_namespace 0
zk_cnt_tempephseq0000000016_write_per_namespace 0
zk_sum_tempephseq0000000016_write_per_namespace 0
zk_avg_tempperseq0000000012_write_per_namespace 0.0
zk_min_tempperseq0000000012_write_per_namespace 0
zk_max_tempperseq0000000012_write_per_namespace 0
zk_cnt_tempperseq0000000012_write_per_namespace 0
zk_sum_tempperseq0000000012_write_per_namespace 0
5、Python操作ZK
Python通过kazoo可以实现操作ZK服务。
5.1 环境准备
kazoo版本2.9.0第三方库存在版本问题,使用PyCharm安装时指定版本号为2.8.0。
第三方包Kazoo安装完成后,打开ZK服务测试连接效果:
from kazoo.client import KazooClient
zk = KazooClient(hosts="192.168.70.128:2181") # ZK服务器IP和Port
zk.start() # 连接ZK
node = zk.get_children(path='/')
print("查看根目录下的子节点:")
print(node)
zk.stop() # 关闭ZK连接
输出结果:
查看根目录下的子节点:
['zookeeper', 'test']
5.2 常用操作函数
下面为Python常用ZK操作方法函数详解:
- start:连接ZK服务;
- create:创建节点;
- get:获取节点值;
- get_children:获取子节点列表;
- get_acls:获取节点ACL列表;
- add_auth:添加认证;
- ensure_path:递归创建路径;
- set:设置节点值;
- set_acls:设置节点ACL;
- delete:删除节点;
- set_hosts:设置客户端主机列表;
- sync:同步数据;
- exists:检查节点是否存在;
- reconfig:重置集群配置;
- command:发送四字命令;
- add_listener:添加监听方法;
- remove_listener:删除监听方法;
- stop:断开ZK服务;
- restart:重启ZK服务;
- close:关闭客户端持有资源;
- server_version:获取连接的ZK服务版本信息;
- unchroot:去除路径中的根目录;
- transaction:创建事务对象。
5.2.1 ZK连接客户端 - KazooClient
Python代码如下:
class KazooClient(object):
def __init__(self, hosts='127.0.0.1:2181',
timeout=10.0, client_id=None, handler=None,
default_acl=None, auth_data=None, sasl_options=None,
read_only=None, randomize_hosts=True, connection_retry=None,
command_retry=None, logger=None, keyfile=None,
keyfile_password=None, certfile=None, ca=None,
use_ssl=False, verify_certs=True, **kwargs):
参数说明:
- hosts:以逗号分隔需要连接的ZK服务器列表,默认格式为本机127.0.0.1:2181;
- timeout:ZK连接超时时限,默认为10s;
- client_id:ZK客户端ID,用于重新建立以前的会话连接,默认为None;
- handler:实现回调处理接口IHandler的类实例,默认为None;
- default_acl:用于创建节点的默认ACL,默认为None;
- auth_data:用于连接的身份验证凭据列表,参数值为add_auth方法接受的scheme, credential元组列表。默认为None;
- read_only:Kazoo 0.6新增参数,需要zookeeper版本为3.4+。允许连接只读服务器,默认为None;
- randomize_hosts:Kazoo 0.6新增参数,随机选择主机,默认为True;
- connection_retry:Kazoo 1.2新增参数,用于与zookeeper重连的KazooRetry对象,也可以是用于创建KazooRetry对象的选项字典,默认为None;
- command_retry:Kazoo 1.2新增参数,用于执行retry方法的KazooRetry对象,也可以是用于创建KazooRetry对象的选项字典,默认为None;
- logger:Kazoo 1.2新增参数,用于代替模块全局日志实例的自定义日志记录程序,默认为None
- keyfile:用于身份验证的SSL密钥文件,默认为None
- keyfile_password:SSL密钥文件密码,默认为None
- certfile:用于身份验证的SSL证书文件,默认为None
- ca:用于身份验证的SSL CA文件,默认为None
- use_ssl:是否使用SSL,默认为False
- verify_certs:当使用SSL时,参数绕过certs验证,默认为True
5.2.2 连接ZK - start()
start(self, timeout=15)
参数说明:连接ZK服务,timeout为等待连接成功的时间,单位为秒。若在指定的时间内没有成功连接,则产生timeout_exception异常。
5.2.3 创建节点 - create()
create(self, path, value=b"", acl=None, ephemeral=False,sequence=False, makepath=False, include_data=False)
参数说明:
- path:创建的节点路径;
- value:节点值,必须是byte类型;
- acl:ACL列表;
- ephemeral:表示节点是否为临时节点;
- sequence:表示节点为顺序节点;
- include_data:表示是否返回节点的ZnodeStat信息;
- makepath:表示当路径不存在时是否创建路径,如果为true,创建的节点路径中间不存在的节点一并创建空值的节点,如果为false,如果路径中间有节点不存在,则报错。
5.2.4 获取路径的子节点列表 - get_children()
get_children(self, path, watch=None, include_data=False)
参数说明:
- path:节点路径;
- watch:监听回调函数,如果设置watch,则在删除节点或者在该节点下创建/删除子节点操作成功时触发;
- include_data:表示是否返回节点的ZnodeStat信息。
5.2.5 获取节点的值 - get()
get(self, path, watch=None)
参数说明:
- path:节点路径;
- watch:监听回调函数,如果设置watch,则在删除节点或者在该节点下创建/删除子节点操作成功时触发。
5.2.6 修改节点的值 - set()
set(self, path, value, version=-1)
参数说明:
- path:节点路径;
- value:新节点值;
- version:期望的要更新的节点版本,如果为-1则表示匹配任何版本。
5.2.7 判断节点是否存在 - exists()
exists(self, path, watch=None)
参数说明:
- path:节点路径;
- watch:监听回调函数,如果设置watch,则在删除节点或者在该节点下创建/删除子节点操作成功时触发。
5.2.8 删除节点 - delete()
delete(self, path, version=-1, recursive=False)
参数说明:
- path:节点路径;
- version:期望的要删除的节点版本,如果为-1则表示匹配任何版本;
- recursive:表示是否递归的删除指定节点及其子节点,默认为False。
5.2.9 关闭连接 - stop()
stop()
停止ZK连接,在尝试重新连接时,调用此方法重连将中止。当连接关闭时,会话失效,zookeeper上与会话关联的临时节点会被删除,会触发这些节点以及它们的父节点的监听事件
5.3 代码操作案例
本章节主要以Python代码体现ZK服务API操作。
5.3.1 简单的增删改查
from kazoo.client import KazooClient
# 配置ZK连接IP和Port
zk = KazooClient(hosts="192.168.70.128:2181")
# 连接ZK
zk.start()
# 查看根目录下子节点
node = zk.get_children("/")
print("查看根目录下子节点")
print(node)
# 递归创建节点
zk.create('/test_zk/001/002/003', b'python create test node', makepath=True)
node = zk.get_children('/test_zk/001/002')
print("查看递归创建的节点信息")
print(node)
# 获取节点的值
node_value = zk.get('/test_zk/001/002/003')
print("查看节点值")
print(node_value)
# 修改节点的值
zk.set('/test_zk/001/002/003', b"python change test node value")
node_value = zk.get('/test_zk/001/002/003')
print("查看修改后的节点值")
print(node_value)
# 递归删除节点,等同于客户端命令deleteall
zk.delete('/test_zk/001/002', recursive=True)
node = zk.get_children('/test_zk/001')
print("查看递归删除后的子节点")
print(node)
# 断开ZK连接
zk.stop()
代码输出结果:
查看根目录下子节点
['zookeeper', 'test']
查看递归创建的节点信息
['003']
查看节点值
(b'python create test node', ZnodeStat(czxid=42949672991, mzxid=42949672991, ctime=1673025651517, mtime=1673025651517, version=0, cversion=0, aversion=0, ephemeralOwner=0, dataLength=23, numChildren=0, pzxid=42949672991))
查看修改后的节点值
(b'python change test node value', ZnodeStat(czxid=42949672991, mzxid=42949672992, ctime=1673025651517, mtime=1673025651523, version=1, cversion=0, aversion=0, ephemeralOwner=0, dataLength=26, numChildren=0, pzxid=42949672991))
查看递归删除后的子节点
[]
5.3.2 监听节点 - watch
创建监听节点。
from kazoo.client import KazooClient
zk = KazooClient(hosts='192.168.70.128:2181')
zk.start()
zk.create('/test_zk/001/002/003', b'python create test node', makepath=True)
# 监听标识函数
def zk_watch(aaa): # 无效参数aaa
print('触发监听标识')
while True:
zk.get('/test_zk/001/002/003', watch=zk_watch)
创建修改被监听节点值的代码,执行一次即触发一次监听函数zk_watch的输出标识。
from kazoo.client import KazooClient
zk = KazooClient(hosts='192.168.70.128:2181')
zk.start()
zk.set('/test_zk/001/002/003', b"python change test node value")
zk.stop()
代码输出结果:
触发监听标识
触发监听标识