使用Kazoo去增刪改查zookeeper

每一次新版本開發,都會有開發頻繁的要求查看以前版本里zookeeper的內部配置,由於我公司規定zookeeper的密鑰是不能輕易給開發人員的,所以每次開發找過來運維就要停下手裏工作去幫忙看一下,這樣一來二去就搞得運維很煩。於是就萌生一個念頭,通過一個工具去查詢zookeeper的節點情況,然後再將這個工具嵌入到django裏做成web界面,讓開發苦逼直接去django裏查。


由於django是python語言寫的,爲了代碼統一不至於看瘋一個人,所以這個工具也要選擇python系,那麼就要使用Kazoo,因爲它比較專業而且成熟。這裏實驗使用的python版本是2.7.5。


安裝Kazoo的方法很簡單,#pip install kazoo。然後啓動zookeeper的服務端,安裝zookeeper的方法去看:http://blog.51cto.com/chenx1242/1889715 。


進入python後,基本操作如下:

>>> from kazoo.client import KazooClient
>>> zk = KazooClient(hosts='Zookeeper的地址:2181')    #如果是本地那就寫127.0.0.1
#zk = KazooClient(hosts='Zookeeper 1的地址:2181,Zookeeper 2的地址:2181,Zookeeper 3的地址:2181')    #如果是zookeeper集羣就這麼寫
>>> zk.start()    #與zookeeper連接,如果是zk.start(timeout=15),就規定了超時時間
>>> zk.state 
'CONNECTED'        #已經連接成功,如果是LOST就是連接失敗
>>> zk.connected 
True                #確認已經連接
>>> zk.stop()    #與zookeeper斷開


如果出現了“kazoo.handlers.threading.KazooTimeoutError: Connection time-out”這個錯誤,請檢查zookeeper的進程是否已經啓動。這裏補充一句,zk.start()是以同步的形式連接服務集羣。


如果要建立一個叫/abc/JQK/XYZ/0001的node,node裏面的value是"this is my house" ,語句如下:

zk.create('/abc/JQK/XYZ/0001',b'this is my house',makepath=True)    
#makepath=True是遞歸創建,如果不加上中間那一段,就是建立一個空的節點
zk.ensure_path('/abc/JQK/XYZ/0001')        #這樣寫是創建空的node


效果如圖:

image.png


如果要刪除這個/abc/JQK/XYZ/0001的子node,但是想要上一級XYZ這個node還是存在的,語句如下:

zk.delete('/abc/JQK/XYZ/0001',recursive=True)    
#recursive=True是遞歸刪除,就是無視下面的節點是否是空,都幹掉,不加上的話,會提示子節點非空,刪除失敗



現在假如要在0001這個node裏更改value,比如改成:“this is my horse!”,語句如下:

>>> zk.set('/abc/JQK/XYZ/0001',"this is my horse!")
ZnodeStat(czxid=80, mzxid=84, ctime=1513913337850, mtime=1513913601610, version=3, cversion=0, aversion=0, ephemeralOwner=0, dataLength=17, numChildren=0, pzxid=80)


注意!set這種增加節點內容的方式是覆蓋式增加,並不是在原有基礎上增添。而且添加中文的話可能在ZooInspecter裏出現的是亂碼,現在我們來到ZooInspecter看一下效果:

image.png


我現在在'/ps/spider/dlb-receiver/'下建立兩個node,一個叫0001,另一個叫0002,現在若要查看“/ps/spider/dlb-receiver/“下面有多少個子節點,語句是:

>>> zk.get_children('/ps/spider/dlb-receiver')
[u'0001', u'0002']      #可見目前只有兩個子節點

>>> children = zk.get_children("/ps/spider/dlb-receiver")    
>>> print("There are %s children with names %s" % (len(children), children)) 
There are 2 children with names [u'0001', u'0002']


假設“/ps/spider/dlb-receiver/0001”它裏面的value如圖:

 image.png


要查看這個“/ps/spider/dlb-receiver/0001”的value,語句是:

>>> zk.get('/ps/spider/dlb-receiver/0001')    #獲得的type是tuple(元組)
('-- 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}', ZnodeStat(czxid=47, mzxid=110, ctime=1513863785337, mtime=1513924538981, version=6, cversion=0, aversion=0, ephemeralOwner=0, dataLength=255, numChildren=0, pzxid=47))
>>> print(zk.get('/ps/spider/dlb-receiver/0001'))    #前面加上print也是可以的
('-- 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}', ZnodeStat(czxid=47, mzxid=110, ctime=1513863785337, mtime=1513924538981, version=6, cversion=0, aversion=0, ephemeralOwner=0, dataLength=255, numChildren=0, pzxid=47))


上面這一大坨tuple看起來很頭疼,那麼就精簡一下:

>>> print(zk.get('/ps/spider/dlb-receiver/0001')[0])    #後面添加一個[0]即可
-- this is mysql
mysql = {
host = "rm-bp116dn17141tx72j.mysql.rds.aliyuncs.com",
port = 3306,
database = "lcyy123ht",
username = "lcyyoalalht",
password = "dvlSdJyuw2ad43fg09",
}
-- this is redis
redis = {
host = "127.0.0.1",
port = 6379,
}

>>> print(zk.get('/ps/spider/dlb-receiver/0001')[1])    #這裏是stat
ZnodeStat(czxid=47, mzxid=118, ctime=1513863785337, mtime=1513926132280, version=8, cversion=2, aversion=0, ephemeralOwner=0, dataLength=261, numChildren=0, pzxid=120)


或者是

>>> data,stat = zk.get('/ps/spider/dlb-receiver/0001')

>>> print (data)
-- this is mysql
mysql = {
host = "rm-bp116dn17141tx72j.mysql.rds.aliyuncs.com",
port = 3306,
database = "lcyy123ht",
username = "lcyyoalalht",
password = "dvlSdJyuw2ad43fg09",
}
-- this is redis
redis = {
host = "127.0.0.1",
port = 6379,
}



但是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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章