ZooKeeper API使用

kazoo

zk是用java开发的,因此sdk对java支持比较好,我们使用的是python语言,借助第三方库kazoo,网站 https://kazoo.readthedocs.io/en/latest/index.html 网站里面有比较详细地介绍kazoo的使用方法和注意事项,我们这里只列举常见的使用方法,具体深入的请前往网站仔细阅读。

安装

安装kazoo比较简单,yum可以使用

yum install python-kazoo

pip可以使用

pip install kazoo

安装成功之后,我们验证一下是否安装可用

[root@localhost ~]# pythonPython 2.7.5 (default, Jul 13 2018, 13:06:57) [GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux2Type "help", "copyright", "credits" or "license" for more information.>>> from kazoo.client import KazooClient>>> #能够import的证明安装成功可用了

CRUD例子

我们先写一个最简单的节点CRUD例子,kazoo这个库它内部会开工作线程执行相关连接和指令操作,不会阻塞主线程,还有在kazoo线程再去执行zk的指令操作会卡死整个程序,这个是需要注意的。

  
  
  1. import signal

  2. import sys

  3. import time

  4. import logging

  5. from kazoo.client import KazooClient

  6. from kazoo.client import KazooState


  7. #用于捕获ctrl+c退出程序

  8. is_exit = False


  9. #记录当前kazoo连接状态

  10. cur_state = None


  11. def sigint_handler(signum, frame):

  12.    global is_exit

  13.    is_exit = True


  14. #回调通知kazoo当前状态,并记录在全局变量 cur_state

  15. def my_listener(state):

  16.    # KazooState.LOST

  17.    # KazooState.CONNECTED

  18.    # KazooState.SUSPENDED

  19.    global cur_state

  20.    print state

  21.    cur_state = state


  22. #相关zk的CRUD指令测试

  23. def do_something():

  24.    #先检查一下是否存在节点 /my/favorite/node

  25.    ret = zk.exists("/my/favorite/node")

  26.    print ret

  27.    if ret:

  28.        #如果节点则删除

  29.        zk.delete("/my/favorite/node", recursive=True)

  30.        return


  31.    #递归创建路径

  32.    zk.ensure_path("/my/favorite")


  33.    #创建节点并设置数据

  34.    zk.create("/my/favorite/node", b"a value")


  35.    #获取节点信息

  36.    data, stat = zk.get("/my/favorite/node")

  37.    print("Version: %s, data: %s" % (stat.version, data.decode("utf-8")))


  38.    #获取子节点信息

  39.    children = zk.get_children("/my/favorite")

  40.    print("There are %s children with names %s" % (len(children), children))



  41. if __name__ == "__main__":

  42.    #ctrl+c

  43.    signal.signal(signal.SIGINT, sigint_handler)

  44.    signal.signal(signal.SIGHUP, sigint_handler)

  45.    signal.signal(signal.SIGTERM, sigint_handler)


  46.    #参考官方用法不报错

  47.    logging.basicConfig()


  48.    #实例一个kazoo对象

  49.    zk = KazooClient(hosts='127.0.0.1:2181')


  50.    #监听kazoo连接状态回调

  51.    zk.add_listener(my_listener)


  52.    #开始

  53.    zk.start()


  54.    while not is_exit:

  55.        time.sleep(1)

  56.        #只有当前状态是连接才去做相关CRUD测试

  57.        #这里不太严谨因为多线程情况下又可能连接突然断掉了还没来得及

  58.        #更新状态然后就去做CRUD操作了,这里仅作为演示代码不考虑复杂情况

  59.        if cur_state and cur_state == KazooState.CONNECTED:

  60.            do_something()

  61.            break    


  62.    #停止kazoo实例

  63.    zk.stop()

监听

除了CRUD常用操作以外,还有一个非常实用的功能就是监听节点(可以是节点的添加、删除、节点的数据更新)。kazoo提供了2种监听节点的方法,第一种是比较简单的,如下面官方提供的代码例子:

  
  
  1. def my_func(event):

  2.    # check to see what the children are now


  3. # Call my_func when the children change

  4. children = zk.get_children("/my/favorite/node", watch=my_func)

这种监听方法,当对应节点触发了,只会通知回调一次,如果需要继续监听需要再手动设置多次监听函数。下面介绍另外一种监听方法,只需要设定一次,每次有事件都会通知到回调函数而且通知类型数据比较丰富。下面列的是官方的例子代码片段,使用了python的装饰器。

  
  
  1. @zk.ChildrenWatch("/my/favorite/node")

  2. def watch_children(children):

  3.    print("Children are now: %s" % children)

  4.    # Above function called immediately, and from then on


  5. @zk.DataWatch("/my/favorite")

  6. def watch_node(data, stat):

  7.    print("Version: %s, data: %s" % (stat.version, data.decode("utf-8")))

一个完整的监听例子代码

  
  
  1. import signal

  2. import sys

  3. import time

  4. import logging

  5. from kazoo.client import KazooClient

  6. from kazoo.client import KazooState


  7. is_exit = False

  8. cur_state = None


  9. def sigint_handler(signum, frame):

  10.    global is_exit

  11.    is_exit = True


  12. def my_listener(state):

  13.    global cur_state

  14.    print state

  15.    cur_state = state


  16. def set_watch():

  17.    #监听 /my/favorite 下的节点事件

  18.    #可以先做上面的测试例子会创建好 /my/favorite 节点或者手动去zk创建

  19.    @zk.ChildrenWatch("/my/favorite")

  20.    def watch_children(children):

  21.        print("Children are now: %s" % children)

  22.        # Above function called immediately, and from then on


  23.    #监听指定节点 /my/favorite/node 事件

  24.    @zk.DataWatch("/my/favorite/node")

  25.    def watch_node(data, stat):

  26.        print("Version: %s, data: %s" % (stat.version, data.decode("utf-8")))    

  27.        print repr(stat)

  28.        print repr(data)


  29. if __name__ == "__main__":

  30.    signal.signal(signal.SIGINT, sigint_handler)

  31.    signal.signal(signal.SIGHUP, sigint_handler)

  32.    signal.signal(signal.SIGTERM, sigint_handler)


  33.    logging.basicConfig()


  34.    zk = KazooClient(hosts='127.0.0.1:2181')


  35.    zk.add_listener(my_listener)


  36.    zk.start()


  37.    is_set_watch = False


  38.    while not is_exit:

  39.        time.sleep(1)

  40.        if cur_state and cur_state == KazooState.CONNECTED:

  41.            #当client建立连接后再设置监听回调

  42.            if not is_set_watch:

  43.                is_set_watch = True

  44.                set_watch()

  45.            else:

  46.                continue


  47.    zk.stop()

测试

先运行测试程序,然后再开一个新的ssh中断使用zkCli.sh连接zk,执行以下测试指令

  
  
  1. #创建一个测试节点

  2. create /my/favorite/test 'test'


  3. #删除测试节点

  4. delete /my/favorite/test


  5. #设置节点数据

  6. set /my/favorite/node '123'

测试程序先后输出如下

  
  
  1. #当创建 test 测试节点的时候,函数回调输出当前节点列表,发现新增节点test

  2. Children are now: [u'node', u'test']


  3. #当删除 test 测试节点的时候,函数回调输出当前节点列表,已经没有节点test

  4. Children are now: [u'node']


  5. #当设置节点node数据时,函数回调输出相关数据信息

  6. Version: 26, data: 123

  7. ZnodeStat(czxid=114, mzxid=204, ctime=1538012242884, mtime=1538035424029, version=26, cversion=0, aversion=0, ephemeralOwner=0, dataLength=3, numChildren=0, pzxid=114)

  8. '123'


猜你喜欢

转载自blog.51cto.com/13475644/2345803