zookeeper examples within kazoo

zookeeper样例,包含:

  • CRUD
  • retry
  • watcher
  • transaction
  • zk异步调用
  • zk锁使用

pip requirement

gevent==22.10.2
greenlet==2.0.2
kazoo==2.9.0
selectors2==2.0.2
six==1.16.0
threadpool==1.3.2
zope.event==4.6
zope.interface==5.5.2

docker部署zookeeper

docker run -id --name zk -p 2181:2181 zookeeper:latest

基本操作样例

import sys
import logging
import os
import pdb
from datetime import datetime

import kazoo.exceptions as zkException
from kazoo.client import KazooClient, KazooState, KeeperState
from kazoo.retry import KazooRetry


logging.basicConfig(stream=sys.stdout, level=logging.INFO)
logger = logging.getLogger()

ZK_WORKDIR = "/workspace"
NODE_NAME = ""

zk = KazooClient(hosts="127.0.0.1:2181")
zk.start()


@zk.add_listener
def watch_for_ro(state):
    """
    zk read only mode watcher
    """
    if state == KeeperState.CONNECTED:
        if zk.client_state == KeeperState.CONNECTED_RO:
            logger.info("Read only mode!")
        else:
            logger.info("Read/Write mode!")


@zk.ChildrenWatch(ZK_WORKDIR)
def watch_workdir_children(children):
    """
    workdir children watcher
    """
    logger.info("Workdir children has been changed, children list: {}".format(children))


@zk.DataWatch(ZK_WORKDIR)
def watch_workdir_node(data, stat):
    """
    workdir node watcher
    """
    logger.info("Workdir node has been changed, data: {}".format(data.decode("utf-8")))


def zk_create():
    """
    zk create/ensure_path example
    """
    zk.ensure_path(ZK_WORKDIR)
    # generate current time
    global NODE_NAME
    NODE_NAME = datetime.now().strftime("%Y%m%d__%H_%M_%S")
    zk.create(os.path.join(ZK_WORKDIR, NODE_NAME), bytes(NODE_NAME, "utf-8"))

    zk.set(ZK_WORKDIR, bytes(NODE_NAME, "utf-8"))


def zk_get():
    """
    zk get/exists/get_children example
    """
    full_node_name = os.path.join(ZK_WORKDIR, NODE_NAME)
    if zk.exists(full_node_name):
        logger.info("Node {} exists.".format(NODE_NAME))
    else:
        logger.info("Node {} not exists.".format(NODE_NAME))

    # get node data
    data, stat = zk.get(full_node_name)
    logger.info("Node version: {}, data: {}".format(stat.version, data.decode("utf-8")))

    # list of workspace
    children = zk.get_children(ZK_WORKDIR)
    logger.info("There are {} children with names {}".format(len(children), children))


def zk_set():
    """
    zk set example
    """
    full_node_name = os.path.join(ZK_WORKDIR, NODE_NAME)

    data, stat = zk.get(full_node_name)
    source_data = data.decode("utf-8")

    zk.set(full_node_name, bytes(source_data + "-edited", "utf-8"))

    data, stat = zk.get(full_node_name)
    logger.info("Node version: {}, data: {}".format(stat.version, data.decode("utf-8")))


def zk_del():
    """
    zk delete example
    """
    full_node_name = os.path.join(ZK_WORKDIR, NODE_NAME)
    children = zk.get_children(ZK_WORKDIR)
    logger.info("There are {} children with names {}".format(len(children), children))

    zk.delete(full_node_name, recursive=True)

    children = zk.get_children(ZK_WORKDIR)
    logger.info("There are {} children with names {}".format(len(children), children))


def zk_crud():
    """
    zk crud example
    """
    # zk create/ensure_path
    zk_create()
    # zk get/exists/get_children
    zk_get()
    # zk set
    zk_set()
    # zk del
    zk_del()


def zk_retry():
    """
    zk retry example
    """
    kr = KazooRetry(max_tries=3, ignore_expire=False)
    result = kr(zk.get_children, ZK_WORKDIR)
    logger.info("Retry result: {}".format(result))


def zk_transaction():
    """
    zk transaction example
    """
    transaction = zk.transaction()
    transaction.check(ZK_WORKDIR, version=1)
    node_name = datetime.now().strftime("transaction__%Y%m%d__%H_%M_%S")
    transaction.create(node_name, bytes(node_name, "utf-8"))
    results = transaction.commit()
    logger.info("transaction result: {}".format(results))

    # check each result
    for result in results:
        if isinstance(result, zkException.BadVersionError):
            logger.error("BadVersionError occurred.")
        elif isinstance(result, zkException.RuntimeInconsistency):
            logger.error("RuntimeInconsistency occurred")


def main():
    """
    main logic
    """
    # zk crud example
    zk_crud()
    # zk retry
    # a better retry example maybe distributed lock
    zk_retry()
    # zk watcher example can be seen above
    # zk transaction
    zk_transaction()

    zk.stop()


if __name__ == '__main__':
    main()

zk异步调用样例

import sys
import logging

from kazoo.client import KazooClient
from kazoo.exceptions import ConnectionLossException, NoAuthException
from kazoo.handlers.gevent import SequentialGeventHandler


logging.basicConfig(stream=sys.stdout, level=logging.INFO)
logger = logging.getLogger()

ZK_WORKDIR = "/workspace"

zk = KazooClient(handler=SequentialGeventHandler())

# returns immediately
event = zk.start_async()

# wait for 30 seconds and see if we are connected
event.wait(timeout=30)

if not zk.connected:
    zk.stop()
    raise Exception("Unable to connect zookeeper.")


def async_callback(async_obj):
    """
    async callback
    """
    try:
        children = async_obj.get()
        logger.info("Workspace children list: {}".format(children))
    except (ConnectionLossException, NoAuthException):
        sys.exit(1)


def main():
    """
    main logic
    """
    async_obj = zk.get_children_async(ZK_WORKDIR)
    async_obj.rawlink(async_callback)


if __name__ == "__main__":
    main()

zk锁操作样例

import os
import sys
import threading
import time

from kazoo.client import KazooClient, KazooState


# zookeeper config
ZK_HOST = ZK_DEFAULT_HOST = '127.0.0.1:2181'
LOCK_NAME = 'test_lock'
LOCK_PATH_ROOT = '/'


class ZooKeeperLock():
    """
    zookeeper lock implement
    """

    def __init__(self, hosts, lock_name, timeout=10):
        """
        init zookeeper lock
        """
        if hosts:
            self.hosts = hosts
        else:
            self.hosts = ZK_DEFAULT_HOST
        self.lock_name = lock_name
        self.timeout = timeout

        self._create()

    def _lock_exists(self):
        """
        check whether lock exists
        """
        if self.lock_handle:
            return True
        return False

    def _create(self):
        """
        create zookeeper lock
        """
        # create zookeeper client
        try:
            self.zk = KazooClient(hosts=self.hosts, timeout=self.timeout)
            self.zk.start(timeout=self.timeout)
        except Exception as e:
            self.init_ret = False
            print('Create KazooClient failed! Exception: %s' % str(e))
            return

        # create lock
        try:
            lock_path = os.path.join(LOCK_PATH_ROOT, self.lock_name)
            self.lock_handle = self.zk.Lock(lock_path)
        except Exception as e:
            self.init_ret = False
            print('Create lock failed! Exception: %s' % str(e))
            return

    def destroy(self):
        """
        destroy zookeeper lock
        """
        # check lock status
        if self._lock_exists() and self.lock_handle.is_acquired:
            raise Exception('Destroy lock failed! Please release lock before it has been destroyed.')
        # unlink zookeeper
        if self.zk:
            self.zk.stop()
            self.zk = None

    def acquire(self, blocking=True, timeout=None):
        """
        acquire zookeeper lock
        """
        # check if lock exists
        if not self.lock_handle:
            return None  

        # try acquire lock
        try:
            return self.lock_handle.acquire(blocking=blocking, timeout=timeout)
        except Exception as e:
            print('Acquire lock failed! Exception: %s' % str(e))
            return None

    def release(self):
        """
        release zookeeper lock
        """
        if not self._lock_exists():
            return None
        return self.lock_handle.release()

    def __del__(self):
        """
        del zookeeper lock
        """
        self.release()
        self.destroy()


def create_lock():
    """
    create zookeeper lock
    """
    zk_lock = ZooKeeperLock(ZK_HOST, LOCK_NAME)
    acquire_result = zk_lock.acquire()
    if not acquire_result:
        print('Cannot acquire lock! Result: %s' % acquire_result)
    print('%s acquired lock.' % threading.current_thread().name)
    time.sleep(0.5)
    zk_lock.release()
    print('%s released lock.' % threading.current_thread().name)
    zk_lock.destroy()


def main():
    """
    main logic
    """
    for i in range(0, 10):
        thread = threading.Thread(target=create_lock)
        thread.start()


if __name__ == '__main__':
    main()
posted @ 2023-02-07 11:39  JHSeng  阅读(118)  评论(0编辑  收藏  举报