zookeeper分布式过程协同技术详解
目录:
1 简介
- zookeeper可以使开发人员可以实现通用的协作任务,包括选举主节点,管理组内成员关系,管理元数据等
- 提供java和c的client
- 独立部署保证扩展性和容错性
- 用于存储映射关系数据,而非应用数据
1.1 zookeeper的使命
zookeeper可以在分布式系统中协作多个任务,一个协作任务是一个包含多个进程的任务。
任务可以是为了协作或者管理竞争。
- 协作就是多个进程需要一同处理一个事情,一些进程采取了某些行动使得其他进程可以继续工作,典型的主从工作模式,从节点处于空闲状态会通知主节点可以接受工作,主节点就会分配任务给从节点
- 竞争就是两个进程不能同时处理工作,一个进程必须等待另一个进程
在主从结构中,都希望成为主节点,需要实现一个互斥排它锁,主节点就是获取到锁的那位
- 对于Hbase,zookeeper用于选取主节点,并追踪服务,确保集群的元数据
- 对于kafka,zookeeper用于检测崩溃,实现topic的注册,保持主题的消费和生产状态
zookeeper的ClientAPI功能
- 保障强一致性,有序行和持久性
- 实现通用的同步原语能力
- 简单的并发处理机制
zookeeper简化了分布式开发流程
zookeeper不适合存储海量的数据
真实分布式系统可能会有以下问题
- 消息延迟
- 处理器性能
- 时间偏移
1.2 主从应用
主从结构
需要考虑的问题
- 主节点崩溃 系统无法分配任务,或重新分配已失败的任务
- 从节点崩溃 已分配的任务无法正常的完成
- 通信故障
对于主节点崩溃,需要有一个其他的节点恢复成主节点崩溃前的状态,就需要从zookeeper获取之前的状态数据。由于主节点负载过高,导致消息延迟,可能会导致备节点成为主节点,部分从节点连接新的主节点,造成脑裂,导致行为不一致。需要预发脑裂和预防主节点失效
对于从节点崩溃,主节点需要能监控到从节点的崩溃,确定哪些从节点可以派发崩溃的任务,并且确认奔溃时节点的任务状态是完成部分或者全部完成没上报状态,必要的时候需要恢复任务到原来的状态
对于通信故障,需要对任务进行锁,防止任务被执行不止一次
总结一下就是
- 主节点需要选举
- 主节点需要检测崩溃或者失去连接的从节点
- 主节点需要知道那些节点可以执行任务
- 主从节点需要具有某些可靠的方式保存分配状态和执行状态
1.3 分布式协作的难点
满足一个节点崩溃不会影响整个集群
2 了解zookeeper
2.1 基础
设计一个用于协作的服务需要提供原语,暴露原语的调用方法(create,acquire和release)并控制这些实例,需要创建原语列表,并且提供API扩展,用于引入新的原语
zookeeper中不直接暴露原语,只是暴露一小部分调用方法组成类似文件系统的API,以便用于实现自己的原语
recipes用来表示原语的实现,包括zookeeper的操作和维护着一个小型数据库的类似文件系统的层级树状结构znode
- worker下为可用从节点
- tasks下为创建并等待执行的任务
- assign下为节点正在处理的任务
2.1.2 API概述
API | 介绍 |
---|---|
create/path data | 创建名为/path的路径,数据为data |
delete/path | 删除/path路径 |
exists/path | 检测/path路径是否存在 |
setData/path data | 设置名为/path的znode的数据为data |
getData/path | 返回名为/path节点的数据信息 |
getChildren/path | 返回所有/path节点的所有子节点列表 |
zookeeper不允许局部写入或读取znode的数据,当设置一个znode节点的数据或读取的时候,znode的数据都会被替换或者读取
2.1.2 znode的类型
znode节点可以是持久节点或临时节点
- 持久节点只能通过delete删除
- 临时节点崩溃或者关闭了与zookeeper的连接就会被删除
用于保存一些持久化数据的就需要持久节点,主从模式的保存任务的分配情况的assign就是一个持久节点
临时znode用于反映应用的信息,主节点创建的znode为临时znode,节点存在标识主节点正常,当节点不存在,节点下的信息也会消失,从节点也是一样,从节点下执行的任务也跟着消失
有序(sequential) 节点,会被分配一个单调递增的整数,这样可以看到创建顺序
2.1.3 监视和通知
zookeeper通常被远程服务的方式调用
如果每次去请求获取数据会执行很多次,就是轮询
为了替换轮询,采用了通知(notification)的方式。client向zookeeper注册需要接受的znode,通过对znode设置监视点watch来接受通知
监视点获取到数据变化就会通知Client,就转换为以下方式
监视点是一个单次操作,在通知发生的时候需要client重新设置监视点,但是设置监视点的时候还会顺便查看一下有没有符合监视点的数据
服务是监视点通知是先进行通知,再进行操作更新
zookeeper可以配置不同的类型通知,例如监控数据变化,znode子节点变化,znode的创建和删除
2.1.4 版本
每个znode都有版本号,会随着数据变化自增,当使用setData和delete需要传入参数,并且参数必须和当前版本号一致才能调用成功
2.2 架构
zookeeper分为
- 单节点的独立模式
- 多节点的仲裁模式
2.2.1 zookeeper仲裁
在仲裁模式,如果Client等待所有的节点都写入数据再继续,延迟会很高。
超过半数的服务器保存了数据就可以认为保存了数据,服务器会保证这个超过半数的数量,例如如果是4个服务器,就需要3个写入
2.2.2 会话
在执行请求的时候,Client会与集群的一个Server建立一个会话,提交会操作也会写入到一个会话的临时节点,如果会话终止则临时会话也会消失,当会话如果不能连到这个Server,会转移会话到另一个服务器
会话提供了先入先出顺序执行,一个Client通常只打开一个会话,就能保证顺序执行
2.3 开始使用zookeeper
当启动服务的时候,独立模式并不复杂,当仲裁模式启动的,启动第一个节点的时候会疯狂连接其他服务器,然后失败,当启动另一个服务器就会进行仲裁法定人数,如果满足就选举leader
使用zkCli.sh,脚本整体流程
- Client启动建立一个会话
- Client尝试连接Server
- 连接成功,Server初始化新的会话
- 会话初始化完成
- Server向Client发送SyncConnented事件
- Client通过SyncConnented通知需要使用watcher处理这个事件
会话的生命周期包括CONNENTING,CONNENTED,CLOSED和NOT_CONNENT,当Client与Server连接有问题,会从CONNENTED跳回括CONNENTING再次连接
这个时间受超时参数影响,在t/3没收到消息会发送心跳,在2t/3时间就会寻找其他的zookeeper节点
建立会话之前Server会返回一个列表,由服务器选择
重连的时候zkid事务标识符
通过zookeeper实现锁,假设一个应用有n个进程,这些进程需要获取一个锁,每个进程都去创建一个/lock的临时节点即可,创建成功的获取到了锁,其他节点就只能监听/lock的变化
2.4 一个主从模式的例子实现
2.4.1 主节点角色
创建主节点(临时节点)
[zk: localhost:2181(CONNECTED) 0] create -e /master "master1.example.com:2223"
Created /master
[zk: localhost:2181(CONNECTED) 1] ls /
[master, zookeeper]
[zk: localhost:2181(CONNECTED) 2] get /master③
"master1.example.com:2223"
cZxid = 0x67
ctime = Tue Dec 11 10:06:19 CET 2012
mZxid = 0x67
mtime = Tue Dec 11 10:06:19 CET 2012
pZxid = 0x67
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x13b891d4c9e0005
dataLength = 26
numChildren = 0
再创建主节点就会失败
[zk: localhost:2181(CONNECTED) 0] create -e /master "master2.example.com:2223"
Node already exists: /master
[zk: localhost:2181(CONNECTED) 1]
获取当前主节点状态
[zk: localhost:2181(CONNECTED) 1] stat /master true
cZxid = 0x67
ctime = Tue Dec 11 10:06:19 CET 2012
mZxid = 0x67
mtime = Tue Dec 11 10:06:19 CET 2012pZxid = 0x67
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x13b891d4c9e0005
dataLength = 26
numChildren = 0
[zk: localhost:2181(CONNECTED) 2]
设置添加监视点
[zk: localhost:2181(CONNECTED) 1] stat /master true
cZxid = 0x67
ctime = Tue Dec 11 10:06:19 CET 2012
mZxid = 0x67
mtime = Tue Dec 11 10:06:19 CET 2012
pZxid = 0x67
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x13b891d4c9e0005
dataLength = 26
numChildren = 0
主节点的会话关闭或者过期
[zk: localhost:2181(CONNECTED) 2]
WATCHER::
WatchedEvent state:SyncConnected type:NodeDeleted path:/master
[zk: localhost:2181(CONNECTED) 2] ls /
[zookeeper]
[zk: localhost:2181(CONNECTED) 3]
就可以创建主节点了
[zk: localhost:2181(CONNECTED) 3] create -e /master "master2.example.com:2223"
Created /master
[zk: localhost:2181(CONNECTED) 4]
2.4.2 从节点,任务和分配
直接创建对应的持久节点
[zk: localhost:2181(CONNECTED) 0] create /workers ""
Created /workers
[zk: localhost:2181(CONNECTED) 1] create /tasks ""
Created /tasks
[zk: localhost:2181(CONNECTED) 2] create /assign ""
Created /assign
[zk: localhost:2181(CONNECTED) 3] ls /
[assign, tasks, workers, master, zookeeper]
[zk: localhost:2181(CONNECTED) 4]
主节点检测/workers和/tasks的子节点变化情况
[zk: localhost:2181(CONNECTED) 4] ls /workers true
[]
[zk: localhost:2181(CONNECTED) 5] ls /tasks true
[]
2.4.3 从节点角色
创建从节点角色,使用
[zk: localhost:2181(CONNECTED) 0] create -e /workers/worker1.example.com
"worker1.example.com:2224"
Created /workers/worker1.example.com
主节点会获取到
WATCHER::
WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/workers
再创建从节点接收任务
[zk: localhost:2181(CONNECTED) 1] create /assign/worker1.example.com ""
Created /assign/worker1.example.com
[zk: localhost:2181(CONNECTED) 2] ls /assign/worker1.example.com true
[]
2.4.4 客户端角色
创建一个队列,按照任务的顺序来添加znode
[zk: localhost:2181(CONNECTED) 0] create -s /tasks/task- "cmd"
Created /tasks/task-0000000000
然后监听任务是否完成
[zk: localhost:2181(CONNECTED) 1] ls /tasks/task-0000000000 true
[]
主节点被通知有任务创建
[zk: localhost:2181(CONNECTED) 6]
WATCHER::
WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/tasks
主节点检测到有任务,获取从节点列表分配从节点到任务
[zk: 6] ls /tasks
[task-0000000000]
[zk: 7] ls /workers
[worker1.example.com]
[zk: 8] create /assign/worker1.example.com/task-0000000000 ""Created /assign/worker1.example.com/task-0000000000
[zk: 9]
从节点被通知有自己的任务
[zk: localhost:2181(CONNECTED) 3]
WATCHER::
WatchedEvent state:SyncConnected type:NodeChildrenChanged
path:/assign/worker1.example.com
从节点获取任务并添加任务状态
[zk: localhost:2181(CONNECTED) 3] ls /assign/worker1.example.com
[task-0000000000]
[zk: localhost:2181(CONNECTED) 4] create /tasks/task-0000000000/status "done"
Created /tasks/task-0000000000/status
[zk: localhost:2181(CONNECTED) 5]
Client收到任务添加了状态,查看以下状态
WATCHER::
WatchedEvent state:SyncConnected type:NodeChildrenChanged
path:/tasks/task-0000000000
[zk: localhost:2181(CONNECTED) 2] get /tasks/task-0000000000
"cmd"
cZxid = 0x7c
ctime = Tue Dec 11 10:30:18 CET 2012
mZxid = 0x7c
mtime = Tue Dec 11 10:30:18 CET 2012pZxid = 0x7e
cversion = 1
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 5
numChildren = 1
[zk: localhost:2181(CONNECTED) 3] get /tasks/task-0000000000/status
"done"
cZxid = 0x7e
ctime = Tue Dec 11 10:42:41 CET 2012
mZxid = 0x7e
mtime = Tue Dec 11 10:42:41 CET 2012
pZxid = 0x7e
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 8
numChildren = 0
[zk: localhost:2181(CONNECTED) 4]
3 使用zookeeper的API
java写的,略
4 处理状态变化
略
5 故障处理
故障点
- zookeeper服务
- 网络
- 应用程序
对于三个Server和两个Client
如果挂掉一个Server,集群还能保持稳定,网络没有问题情况下断掉的Client会连接新的Server
5.1 可恢复故障
当Client不能获取Server的连接,当Client发现自己处于这种无法提供一致性保障的情况下,使用Disconnected事件和ConnectionLossException异常来表示不能识别系统当前状态,然后不断的与其他的Server建立连接。一旦会话被重新建立就会产生一个SyncConnected事件,获取在失去连接这段时间因为变更产生的监视点事件
在Client发送某些请求的时候,如果连接断开了,Client无法确定请求是否被执行
当一个作为master的Client断开连接,重新恢复的时候其他client已经成为master,原来的master必须停止实现master的功能
已存在的监视点与Disconnected事件
为了使里连接断开与重新建立会话更加平滑,zookeeper的Client库会在新的Server上重新建立监视点,并发送监视点列表和最后已知的zkid,Server会根据zkid获取到之后的修改返回给Client
每个操作都需要是符合逻辑的,除了exists,因为exists可以在一个不存在的节点设置监视点,这样可能会有坑
5.2 不可恢复故障
有些情况可能会导致会话无法恢复而必须关闭,这种情况最常见的原因是会话过期,另一个原因就是已认证的会话无法再次与zookeeper的Server完成认证,这两种情况都会出现丢失会话的状态
对于这种状态就会造成临时性节点的丢失
当Client无法提供适当的认证信息来完成会话认证,或DisConnected事件后Client重新连接到已过期的会话,就会发生不可恢复故障
处理不可恢复故障的最简单方法就是中止进程并重启,这样可以使进程恢复原状,通过一个新的会话重新初始化自己的状态,如果该进程继续工作,首先需要清除与旧会话关联的进程状态信息然后初始化新的状态
5.3 群首选举和外部资源
在主机过载的时候,zookeeper是无法保护与外部设备的交互操作
- 一方面Client无法正常发送心跳
- 另一方面主机调度导致不能响应导致会话超时
- 在t1时刻,因为超载导致c1没有响应,但是已经在等待对外部资源的更新了
- 在t2时刻,server声明c1会话终止,删除了c1的临时节点
- 在t3时刻,c2称为主节点
- 在t4时刻,c2改变了外部资源
- 在t5时刻,c1负载下降,发送已序列化好的更新到外部资源
- 在t6时刻,c1与Server重建连接,发现过期并丢失了管理权,但是在t5时刻已经更新了外部资源导致了系统状态损坏
一种情况就是保证主机的性能,另一种方式就是采用隔离
隔离是采用符号,只有最新的符号才能进行修改,czxid就是隔离符号
当访问外部资源的时候,也是使用资源符号,如果外部资源收到了更高的隔离符号,就会拒绝这次请求
当然需要外部资源对隔离符号的识别
6 Zookeeper注意事项
6.1 使用ACL
创建节点等都需要管理访问控制权限,而子节点不会继承父节点的访问权限
6.2 恢复会话
- 在恢复会话后不要使用缓存的状态,要以Server端为可信源
- client崩溃但是提交给任务可能已经完成了,所以要在恢复之后再次进行操作,例如删除
6.3 当znode节点重新创建会重置版本号
client再进行版本号检查的时候可能会有问题
6.4 sync方法
正常应该是使用从Server获取数据,而不是client之间sync数据
6.5 顺序性保障
- 连接丢失时的顺序性 丢失连接在异步调用的时候会用结果码标识,同步时直接报异常,都不会进行重传
- 同步API和多线程的顺序性
- 同步和异步的混合调用顺序性
6.6 数据字段和子节点的限制
zookeeper对数据传输限制为1MB,该限制为任何节点数据字段的最大存储字段,也就限制了父节点可以拥有的子节点数量,当然大小限制可以改变的
如果一个znode下有很大的数据,就会消耗很多的时间在处理上,甚至会导致处理管道停滞
6.7 嵌入式zookeeper服务器
略
7 C语言客户端
略
8 Curator:Zookeeper API的高级封装
略
9 Zookeeper内部运行原理
9.1 请求,事务和标识符
Server对于请求(exists,getData和getChildren)会在本地处理,而create,delete和setChildren请求则会呗转发到Leader上,Leader会形成状态的更新,被称为事务。
其他Server接受到事务的时候,用值覆盖值,也用版本号覆盖版本号,确保集群的原子操作
zkid是一个long性的64位整数,分为32位时间戳和32位计数器
9.2 群首选举
Leader作用是分发事务
每个Server节点在启动后进入Looking状态,开始寻找Leader然后同步自身的状态与Leader一致,而当所有Server都处于Looking状态选举Leader,选举完Leader,其他的节点变为Following状态
Looking状态会向其他Server节点发送通知消息,就是选票信息vota,服务器标识符sid和最近执行的事务zkid
当一个Server节点收到一个投票,根据投票信息与自己的比对,选择更大的zkid信息和对应的sid放到投票,所以新的服务器会赢得选举
但是也有例外,例如Server节点做了错误的判断
s2因为没有收到s1的请求,认为s3为Leader,但是s3收到s1的消息,确认是s1为Leader,也会同步给s2
如果s2多等待一会就能避免这个情况,默认是200ms
9.3 Zab:状态更新的广播协议
Zab是Zookeeper的原子性广播协议,分两个阶段
- Leader向所有Following发送一个PROPOSAL(提案)消息p
- 当一个Following接收到消息p之后会返回一个ACK消息,通知Leader已经接收到PROPOSAL
- 当超过仲裁数量发送了ACK的消息,Leader会通知Following进行提交操作
Zab保障了事务的提交顺序和不会跳过任何事务,一个群首已经提交完之前时间戳需要提交的事务,再任何时间都不会出现两个被仲裁支持的群首
9.4 观察者
观察者不参与选举,仅仅学习经由INFORM消息提交的提议,而Following第一次获取提交的内容,第二次获取提交信息的zkid
引入观察者主要目的是为了提高读请求的可扩展性,另一个就是进行跨数据中心部署
9.5 服务器构成
9.5.1 独立服务器
包含三种请求器PreRequestProcessor,SyncRequestProcessor和FinalRequestProcessor
- PreRequestProcessor接受Client的请求并执行请求,处理结果则是生成一个事务
- SyncRequestProcessor负责持久化事务到磁盘
- FinalRequestProcessor如果有request会接受对zookeeper数据树的修改,否则从数据树读取数据返回
9.5.2 群首服务器
- PreRequestProcessor接受Client的请求
- ProposalRequestProcessor准备提议并将其发送给Following,然后将请求转发到CommitRequestProcessor
- SyncRequestProcessor会持久化事务到磁盘,之后触发AckRequestProcessor处理器
- AckRequestProcessor生成确认消息返回给SyncRequestProcessor
- CommitRequestProcessor收到足够的确认消息就会将提交操作发送
- FinalRequestProcessor执行提交操作
9.5.3 跟随者和观察者服务器
- FollowerRequestProcessor用于接收Client的请求,会将请求转发到CommitRequestProcessor,同时也会转发到Leader
- CommitRequestProcessor对于写请求直接转发到FinalRequestProcessor处理,对于写请求会等待提交事务才能转发到FinalRequestProcessor
- Leader收到写操作会生成提议转发给Follower
- Follow的SyncRequestProcessor在收到提议后会向Leader确认
- Leader收到足够确认消息来提交这个提议,Leader会发送提交事务给Follower,同时也会发送给观察者
- Follower通过接收到提交事务,执行写请求并阻塞其他写请求,保证顺序写入
9.6 本地存储
9.6.1 日志和磁盘的写入
Server会将提议持久化到提议日志,SyncRequestProcessor会及时冲刷到磁盘
补白padding是在文件中预分配磁盘存储块,涉及到存储块分配的文件系统元数据的更新,不会显著影响文件的写入操作
9.6.2 快照
略
9.7 服务器与会话
会话与临时节点,监听点,请求有序都密切相关
9.8 服务器与监视点
监视点只会存在内存中,不会持久化到磁盘,会话断开后会从内存中删除,client也会维护一份监视点,用于重连后同步到Server
9.9 客户端
略
9.10 序列化
略
10 运行zookeeper
所有的投票的Server必须有相同配置
10.1 配置zookeeper服务器
启动从一个zoo.cfg的配置文件读取所有选项,/data目录下的myid用于区分各个服务器
10.1.1 基本配置
- clientPort 监听的TCP端口,默认2181
- dataDir 配置内存数据快照的目录,可以单独配置dataLogDir目录存储日志
- tickTime 单位为毫秒,默认为3000ms,zookeeper中的超时单位基本都是通过其指定,最小超时时间为一个tick,client最小会话时间为2tick,更小的tick可以更及时的发现超时,但是也会造成更高的心跳流量
10.1.2 存储配置
- preAllocSize 预分配的事务日志文件的大小,单位为KB,当写入事务文件,每次都会分配配置值的存储大小,默认值为64MB,但是由于每次快照都会重新生成事务文件,所以可以调小
- snapCount 每次快照的间隔的事务数,默认是100000,用于重启恢复,恢复包含读取快照和快照后的事务,为了防止集群集体执行快照,会使用一个接近snapCount值的随机数
- autopurge.snapRetainCount 当数据清理的时候保留的事务日志和快照数量,最小值和默认值为3
- autopurge.purgeInterval 数据清理的间隔时间,默认为0,就是不进行回收,需要执行zkCleanup.sh手动操作
- fsync.warningthresholdms 触发告警的存储同步时间阀值,默认值为1000ms
- weight.x=n 仲裁时服务器的权重,默认都是1
- traceFile 用于持续跟踪zookeeper的操作,默认没有开启
10.1.3 网络配置
- globalOutstandingLimit 待处理请求的最大值,防止Server的内存溢出,但是也不是硬限制,默认是1000
- maxClientCnxns 允许每个IP地址的并发的socket数量,防止dos,默认为60,这个是针对Server,如果集群5个节点就是300连接
- clientPordAddress 绑定的网卡
- minSessionTimeout 最小会话超时时间,单位为毫秒,Client与Server建立连接的时候会确认一个明确的超时时间,但是不会小于这个
- maxSessionTimeout 同上,为最大
10.1.4 集群配置
- initLimit Follower最初连接到Leader的超时时间,单位为tick的倍数
- syncLimit Follower与Leader同步的超时时间,单位为tick的倍数
- leaderServes Leader服务器是否为client提供服务,配置值为yes和no,默认为yes
- server.x=[hostname]:n:n[:observer] 通讯地址
- cnxTimeout leader打开一个新的连接的超时时间
- electionAlg 选举算法的配置选项
10.2 配置zookeeper集群
略
10.3 重配置
通过3.5版本的reconfig命令
10.4 配额管理
提供了znode的节点数量和节点大小的配额管理的支持,如果超过配额只会触发记录告警日志而不会限制操作执行
[zk: localhost:2181(CONNECTED) 2] create /application ""
Created /application
[zk: localhost:2181(CONNECTED) 3] create /application/superApp super
Created /application/superApp
[zk: localhost:2181(CONNECTED) 4] setquota -b 10 /application/superApp
Comment: the parts are option -b val 10 path /application/superApp
[zk: localhost:2181(CONNECTED) 5] listquota /application/superApp
absolute path is /zookeeper/quota/application/superApp/zookeeper_limits
Output quota for /application/superApp count=-1,bytes=10
Output stat for /application/superApp count=1,bytes=5
在执行
create /application/superApp/lotsOfData ThisIsALotOfData
就会看到
Quota exceeded: /application/superApp bytes=21 limit=10的日志
10.5 多租赁配置
略,基于ACL
10.6 文件系统布局和格式
数据存储分为事务日志和快照两部分,都以普通文件的方式存在文件系统
10.7 四字母命令
- ruok 检测运行状态,会返回imok
- stat 检查状态
- srvr 和stat一样,忽略连接情况
- dump 列出会话信息,只能在Leader上运行
- conf 列出服务器启动运行所使用的基本配置参数
- envi 列出Java环境参数
- mntr 比stat更详细的服务器统计
- wchs 列出服务器的监视点信息
- wchc 列出服务器的监视点的详细信息,并分组
- wchp
- cons 列出每个服务器上的每个连接的统计信息
- crst 重置上边计数器为0
$ echo ruok | nc -v 127.0.0.1 2181
Ncat: Version 7.50 ( https://nmap.org/ncat )
Ncat: Connected to 127.0.0.1:2181.
imokNcat: 5 bytes sent, 4 bytes received in 0.01 seconds.
可以看到返回的imok
10.8 JMX监控
略
10.9 zookeeper工具
略