zookeeper支持四字命令获取节点的内部状态,所谓的四字命令,就是往zookeeper配置的ip和服务端口发送srvr/ruok之类的字符串,zookeeper返回内部状态的命令。具体的有:
conf:输出相关服务配置的详细信息。比如端口、zk数据及日志配置路径、最大连接数,session超时时间、serverId等。
cons:列出所有连接到这台服务器的客户端连接/会话的详细信息。包括“接受/发送”的包数量、session id 、操作延迟、最后的操作执行等信息
crst:重置当前这台服务器所有连接/会话的统计信息
dump:列出未经处理的会话和临时节点(只在leader上有效)
envi:输出关于服务器的环境详细信息(不同于conf命令),比如host.name、java.version、java.home、user.dir=/data/zookeeper-3.4.6/bin之类信息
ruok:测试服务是否处于正确运行状态。如果正常返回”imok”,否则返回空
srst:重置服务器的统计信息
srvr:输出服务器的详细信息。zk版本、接收/发送包数量、连接数、模式(leader/follower)、节点总数
stat:输出服务器的详细信息:接收/发送包数量、连接数、模式(leader/follower)、节点总数、延迟。 所有客户端的列表
wchs:列出服务器watches的简洁信息:连接总数、watching节点总数和watches总数
wchc:通过session分组,列出watch的所有节点,它的输出是一个与 watch 相关的会话的节点列表。如果watches数量很大的话,将会产生很大的开销,会影响性能,小心使用
wchp:通过路径分组,列出所有的 watch 的session id信息。它输出一个与 session 相关的路径。如果watches数量很大的话,将会产生很大的开销,会影响性能,小心使用
mntr:列出集群的健康状态。包括“接受/发送”的包数量、操作延迟、当前服务模式(leader/follower)、节点总数、watch总数、临时节点总数
现在如果需要在go代码中,通过四字命令获取服务器状态,请求应答的过程比较简单,提取具体数字的过程考验对正则表达式的理解。
[root@VM_15_146_centos ~]# echo srvr | nc 127.0.0.1 2283 Zookeeper version: 3.4.14-4c25d480e66aadd371de8bd2fd8da255ac140bcf, built on 03/06/2019 16:18 GMT Latency min/avg/max: 0/0/56 Received: 7274380 Sent: 7274376 Connections: 4 Outstanding: 0 Zxid: 0x1000002a19 Mode: follower Node count: 23228
上面是执行一次srvr命令得到的输出,我们要从这个字符串(tcp连接读出的[]byte)中解析出版本、构建时间和其他所有指标。
const ( zrVer = `^Zookeeper version: ([A-Za-z0-9\.\-]+), built on (\d\d/\d\d/\d\d\d\d \d\d:\d\d [A-Za-z0-9:\+\-]+)` zrLat = `^Latency min/avg/max: (\d+)/(\d+)/(\d+)` zrNet = `^Received: (\d+).*\n^Sent: (\d+).*\n^Connections: (\d+).*\n^Outstanding: (\d+)` zrState = `^Zxid: (0x[A-Za-z0-9]+).*\n^Mode: (\w+).*\n^Node count: (\d+)` ) re, err := regexp.Compile(fmt.Sprintf(`(?m:\A%v.*\n%v.*\n%v.*\n%v)`, zrVer, zrLat, zrNet, zrState)) matches := re.FindAllStringSubmatch(string(response), -1)
在这些正则表达式中,()扩起的部分,在FindAllStringSubmatch调用中,将会按照二维数组方式返回,自己数是第几个,取到对应的字段。
这个字符串确定只会匹配上一次,因此可以直接使用matches[0]赋值将匹配结果降为一维数组,数组元素就是各个字段的值。
在上面,match[0]是版本号,match[1]是构建时间,以此类推下去。