利用正则表达式解析zookeeper四字命令输出

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]是构建时间,以此类推下去。