Categories
DevOps

How to use ZooKeeper to lock resources with a Python script

Use ZooKeeper to lock resources with a Python script.

Create lock_example.py Python script.

#!/usr/bin/env python3

import argparse
import time
from datetime import datetime

from kazoo.client import KazooClient


class ApplicationNode(object):

    lock_time: int

    def __init__(self, chroot, lock_path, lock_identifier, lock_time, zookeeper_hosts):
        self.zookeeper = KazooClient(hosts=zookeeper_hosts)

        self.patch_chroot = chroot
        self.lock_path = lock_path
        self.lock_identifier = lock_identifier

        self.lock_time = lock_time

        self.connect()
        self.chroot()

    def connect(self):
        self.zookeeper.start()

    def chroot(self):
        self.zookeeper.ensure_path(self.patch_chroot)
        self.zookeeper.chroot = self.patch_chroot

    def lock(self):
        lock = self.zookeeper.Lock(self.lock_path, self.lock_identifier)
        with lock:
            print("At {0} the {1} got lock {2} (will sleep for {3}s)".format(
                (datetime.now()).strftime("%B %d, %Y %H:%M:%S"), self.lock_identifier,
                self.lock_path,
                self.lock_time)
            )
            time.sleep(self.lock_time)

    def __del__(self):
        self.zookeeper.close()


if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='ZooKeeper example application')
    parser.add_argument('--chroot')
    parser.add_argument('--path')
    parser.add_argument('--identifier')
    parser.add_argument('--time', type=int)
    parser.add_argument('--zookeeper')

    args = parser.parse_args()

    locker = ApplicationNode(lock_path=args.path, lock_identifier=args.identifier, chroot=args.chroot,
                             lock_time=args.time, zookeeper_hosts=args.zookeeper)

    while True:
        locker.lock()

Use it to play with locks for a particular resource.

$ python3 lock_example.py --chroot /sleeper_app --identifier client_1 --path /particular_resource --time 10 --zookeeper 172.16.0.111:2181,172.16.0.112:2181,172.16.0.113:2181
At June 15, 2021 23:17:16 the client_1 got lock /particular_resource (will sleep for 10s)
At June 15, 2021 23:17:46 the client_1 got lock /particular_resource (will sleep for 10s)
At June 15, 2021 23:18:16 the client_1 got lock /particular_resource (will sleep for 10s)
At June 15, 2021 23:18:46 the client_1 got lock /particular_resource (will sleep for 10s)
At June 15, 2021 23:19:16 the client_1 got lock /particular_resource (will sleep for 10s)
At June 15, 2021 23:19:46 the client_1 got lock /particular_resource (will sleep for 10s)
At June 15, 2021 23:20:12 the client_1 got lock /particular_resource (will sleep for 10s)
^C
$ python3 lock_example.py --chroot /sleeper_app --identifier client_2 --path /particular_resource --time 15 --zookeeper 172.16.0.111:2181,172.16.0.112:2181,172.16.0.113:2181
At June 15, 2021 23:17:26 the client_2 got lock /particular_resource (will sleep for 15s)
At June 15, 2021 23:17:56 the client_2 got lock /particular_resource (will sleep for 15s)
At June 15, 2021 23:18:26 the client_2 got lock /particular_resource (will sleep for 15s)
At June 15, 2021 23:18:56 the client_2 got lock /particular_resource (will sleep for 15s)
At June 15, 2021 23:19:26 the client_2 got lock /particular_resource (will sleep for 15s)
At June 15, 2021 23:19:56 the client_2 got lock /particular_resource (will sleep for 15s)
^C
$ python3 lock_example.py --chroot /sleeper_app --identifier client_3 --path /particular_resource --time 5 --zookeeper 172.16.0.111:2181,172.16.0.112:2181,172.16.0.113:2181
At June 15, 2021 23:17:41 the client_3 got lock /particular_resource (will sleep for 5s)
At June 15, 2021 23:18:11 the client_3 got lock /particular_resource (will sleep for 5s)
At June 15, 2021 23:18:41 the client_3 got lock /particular_resource (will sleep for 5s)
At June 15, 2021 23:19:11 the client_3 got lock /particular_resource (will sleep for 5s)
At June 15, 2021 23:19:41 the client_3 got lock /particular_resource (will sleep for 5s)
At June 15, 2021 23:20:11 the client_3 got lock /particular_resource (will sleep for 5s)
^C

Beware, the error handling is missing to keep this example more concise.