每一次新版本开发,都会有开发频繁的要求查看以前版本里zookeeper的内部配置,由于我公司规定zookeeper的密钥是不能轻易给开发人员的,所以每次开发找过来运维就要停下手里工作去帮忙看一下,这样一来二去就搞得运维很烦。于是就萌生一个念头,通过一个工具去查询zookeeper的节点情况,然后再将这个工具嵌入到django里做成web界面,让开发苦逼直接去django里查。
由于django是python语言写的,为了代码统一不至于看疯一个人,所以这个工具也要选择python系,那么就要使用Kazoo,因为它比较专业而且成熟。这里实验使用的python版本是2.7.5。
进入python后,基本操作如下:
1
2
3
4
5
6
7
8
9
<code>>>> from kazoo.client </code><code>import</code> <code>KazooClient</code>
<code>>>> zk = KazooClient(hosts=</code><code>'Zookeeper的地址:2181'</code><code>) </code><code>#如果是本地那就写127.0.0.1</code>
<code>#zk = KazooClient(hosts='Zookeeper 1的地址:2181,Zookeeper 2的地址:2181,Zookeeper 3的地址:2181') #如果是zookeeper集群就这么写</code>
<code>>>> zk.start() </code><code>#与zookeeper连接,如果是zk.start(timeout=15),就规定了超时时间</code>
<code>>>> zk.state </code>
<code>'CONNECTED'</code> <code>#已经连接成功,如果是LOST就是连接失败</code>
<code>>>> zk.connected </code>
<code>True </code><code>#确认已经连接</code>
<code>>>> zk.stop() </code><code>#与zookeeper断开</code>
如果出现了“kazoo.handlers.threading.KazooTimeoutError: Connection time-out”这个错误,请检查zookeeper的进程是否已经启动。这里补充一句,zk.start()是以同步的形式连接服务集群。
如果要建立一个叫/abc/JQK/XYZ/0001的node,node里面的value是"this is my house" ,语句如下:
<code>zk.create(</code><code>'/abc/JQK/XYZ/0001'</code><code>,b</code><code>'this is my house'</code><code>,makepath=True) </code>
<code>#makepath=True是递归创建,如果不加上中间那一段,就是建立一个空的节点</code>
<code>zk.ensure_path(</code><code>'/abc/JQK/XYZ/0001'</code><code>) </code><code>#这样写是创建空的node</code>
效果如图:
如果要删除这个/abc/JQK/XYZ/0001的子node,但是想要上一级XYZ这个node还是存在的,语句如下:
<code>zk.delete(</code><code>'/abc/JQK/XYZ/0001'</code><code>,recursive=True) </code>
<code>#recursive=True是递归删除,就是无视下面的节点是否是空,都干掉,不加上的话,会提示子节点非空,删除失败</code>
现在假如要在0001这个node里更改value,比如改成:“this is my horse!”,语句如下:
<code>>>> zk.</code><code>set</code><code>(</code><code>'/abc/JQK/XYZ/0001'</code><code>,</code><code>"this is my horse!"</code><code>)</code>
<code>ZnodeStat(czxid=80, mzxid=84, ctime=1513913337850, mtime=1513913601610, version=3, cversion=0, aversion=0, ephemeralOwner=0, dataLength=17, numChildren=0, pzxid=80)</code>
注意!set这种增加节点内容的方式是覆盖式增加,并不是在原有基础上增添。而且添加中文的话可能在ZooInspecter里出现的是乱码,现在我们来到ZooInspecter看一下效果:
我现在在'/ps/spider/dlb-receiver/'下建立两个node,一个叫0001,另一个叫0002,现在若要查看“/ps/spider/dlb-receiver/“下面有多少个子节点,语句是:
<code>>>> zk.get_children(</code><code>'/ps/spider/dlb-receiver'</code><code>)</code>
<code>[u</code><code>'0001'</code><code>, u</code><code>'0002'</code><code>] </code><code>#可见目前只有两个子节点</code>
<code>>>> children = zk.get_children(</code><code>"/ps/spider/dlb-receiver"</code><code>) </code>
<code>>>> print(</code><code>"There are %s children with names %s"</code> <code>% (len(children), children)) </code>
<code>There are 2 children with names [u</code><code>'0001'</code><code>, u</code><code>'0002'</code><code>]</code>
假设“/ps/spider/dlb-receiver/0001”它里面的value如图:
要查看这个“/ps/spider/dlb-receiver/0001”的value,语句是:
<code>>>> zk.get(</code><code>'/ps/spider/dlb-receiver/0001'</code><code>) </code><code>#获得的type是tuple(元组)</code>
<code>(</code><code>'-- this is mysql\r\nmysql = {\r\n\thost = "rm-bp116dn17141tx72j.mysql.rds.aliyuncs.com",\r\n\tport = 3306,\r\n\tdatabase = "lcyy123ht",\r\n\tusername = "lcyyoalalht",\r\n\tpassword = "dvlSdJyuw2ad43fg09",\r\n}\r\n\r\n-- this is redis\r\nredis = {\r\n\thost = "127.0.0.1",\r\n\tport = 6379,\r\n}'</code><code>, ZnodeStat(czxid=47, mzxid=110, ctime=1513863785337, mtime=1513924538981, version=6, cversion=0, aversion=0, ephemeralOwner=0, dataLength=255, numChildren=0, pzxid=47))</code>
<code>>>> print(zk.get(</code><code>'/ps/spider/dlb-receiver/0001'</code><code>)) </code><code>#前面加上print也是可以的</code>
上面这一大坨tuple看起来很头疼,那么就精简一下:
10
11
12
13
14
15
16
17
<code>>>> print(zk.get(</code><code>'/ps/spider/dlb-receiver/0001'</code><code>)[0]) </code><code>#后面添加一个[0]即可</code>
<code>-- this is mysql</code>
<code>mysql = {</code>
<code>host = </code><code>"rm-bp116dn17141tx72j.mysql.rds.aliyuncs.com"</code><code>,</code>
<code>port = 3306,</code>
<code>database = </code><code>"lcyy123ht"</code><code>,</code>
<code>username = </code><code>"lcyyoalalht"</code><code>,</code>
<code>password = </code><code>"dvlSdJyuw2ad43fg09"</code><code>,</code>
<code>}</code>
<code>-- this is redis</code>
<code>redis = {</code>
<code>host = </code><code>"127.0.0.1"</code><code>,</code>
<code>port = 6379,</code>
<code>>>> print(zk.get(</code><code>'/ps/spider/dlb-receiver/0001'</code><code>)[1]) </code><code>#这里是stat</code>
<code>ZnodeStat(czxid=47, mzxid=118, ctime=1513863785337, mtime=1513926132280, version=8, cversion=2, aversion=0, ephemeralOwner=0, dataLength=261, numChildren=0, pzxid=120)</code>
或者是
<code>>>> data,stat = zk.get(</code><code>'/ps/spider/dlb-receiver/0001'</code><code>)</code>
<code>>>> print (data)</code>
但是Kazoo也有非常蛋疼的一面,就比如上面的例子,我只想要redis而不想显示mysql的话,kazoo自带的函数是无法做到的,这就必须要自己写python,通过正则表达式来获取了。
参考文章:https://kazoo.readthedocs.io/en/latest/index.html
参考文章:http://izualzhy.cn/c/cpp/2016/10/05/zookeeper-python-kazoo-introduction
本文转自 苏幕遮618 51CTO博客,原文链接:http://blog.51cto.com/chenx1242/2053627