简介
Tooz项目旨在通过提供协调API帮助开发人员构建分布式应用程序,集中最常见的分布式 基元 ,如组成员协议、锁服务和领导选举。
安装
$ pip install tooz
案例入门
创建一个协调器(Coordinator)
tooz提供的主要对象是协调器。 它允许您使用各种特性,例如组成员、领导人选举或分布式锁定。
tooz协调器提供的特性是使用不同的驱动实现的。 在创建协调器时,需要指定要使用哪个后端驱动程序。 不同的驱动程序可能提供不同的功能集。
如果驱动程序不支持某个特性,它将引发一个 NotImplemented
异常。
下面示例使用基于ZooKeeper的驱动程序加载一个基本的协调器。
from tooz import coordination coordinator = coordination.get_coordinator('zake://', b'host-1') coordinator.start() coordinator.stop()
传递给协调器的第二个参数必须是标识正在运行的程序的唯一标识符。
在创建协调器之后,可以使用提供的各种特性。
为了保持与协调服务器的连接处于活跃状态,必须定期调用heartbeat()方法。 这将确保参与协调的其他程序不会认为协调程序已经死亡。 可以通过传递 start_heart 参数来使用tooz内置的heartbeat管理器,或者自已手动调用它。
from tooz import coordination coordinator = coordination.get_coordinator('zake://', b'host-1') coordinator.start(start_heart=True) coordinator.stop()
请注意,某些驱动程序(如memcached)严重依赖超时,因此用于运行心跳的间隔非常重要 。
组成员(Group Membership)
基本操作
协调器提供的特性之一是处理组成员关系的能力。 一旦创建了一个组,任何协调器都可以加入该组并成为其成员。 可以在成员加入或离开组时通知任何协调器。
import uuid import six from tooz import coordination coordinator = coordination.get_coordinator('zake://', b'host-1') coordinator.start() # Create a group group = six.binary_type(six.text_type(uuid.uuid4()).encode('ascii')) request = coordinator.create_group(group) request.get() # Join a group request = coordinator.join_group(group) request.get() coordinator.stop()
注意,所有操作都是异步的。 这意味着在调用 tooz.coordination.CoordAsyncResult.get()
方法之前,您不能确保您的组已经创建或加入。
通过调用 tooz.coordination.CoordinationDriver.leave_group()
方法可以离开已经加入的组。调用 tooz.coordination.CoordinationDriver.get_groups()
方法可可检索到所有可用组的列表的
观察组的变化
当组的成员列表发生更改时,可以监视并得到通知。 每当组中发生变化时,运行回调函数是很有用的。
import uuid import six from tooz import coordination coordinator = coordination.get_coordinator('zake://', b'host-1') coordinator.start() # Create a group group = six.binary_type(six.text_type(uuid.uuid4()).encode('ascii')) request = coordinator.create_group(group) request.get() def group_joined(event): # Event is an instance of tooz.coordination.MemberJoinedGroup print(event.group_id, event.member_id) coordinator.watch_join_group(group, group_joined) coordinator.stop()
使用 tooz.coordination.CoordinationDriver.watch_join_group()
和 tooz.coordination.CoordinationDriver.watch_leave_group(),
应用程序可以在每个成员加入或离开一个组时得到通知。停止监视事件, tooz.coordination.CoordinationDriver.unwatch_join_group()
和 tooz.coordination.CoordinationDriver.unwatch_leave_group()
允许注销特定回调的注册。
领导者的选举
每个组可以选举自己的领袖。 在一个组中,一次只能有一个领导者。 只有竞选的成员才能当选。 一旦某位领导人下台或挂掉,就会有一位正在竞选的新成员当选。
import time import uuid import six from tooz import coordination ALIVE_TIME = 1 coordinator = coordination.get_coordinator('zake://', b'host-1') coordinator.start() # Create a group group = six.binary_type(six.text_type(uuid.uuid4()).encode('ascii')) request = coordinator.create_group(group) request.get() # Join a group request = coordinator.join_group(group) request.get() def when_i_am_elected_leader(event): # event is a LeaderElected event print(event.group_id, event.member_id) # Propose to be a leader for the group coordinator.watch_elected_as_leader(group, when_i_am_elected_leader) start = time.time() while time.time() - start < ALIVE_TIME: coordinator.heartbeat() coordinator.run_watchers() time.sleep(0.1) coordinator.stop()
tooz.coordination.CoordinationDriver.watch_elected_as_leader()
允许注册一个函数,该函数将在成员当选为leader时被回调。 tooz.coordination.CoordinationDriver.unwatch_elected_as_leader()
方法可以取消所有回调的注册从而来停止运行。通过 tooz.coordination.CoordinationDriver.stand_down_group_leader()
方法也可以暂时退出领导地位。 可以使用 tooz.coordination.CoordinationDriver.get_leader()
检索一个组的leader, 即使不属于这个组也可以检索到。
锁
Tooz提供分布式锁。 锁是通过名称标识的,一次只能由一个协调器获取锁。
from tooz import coordination coordinator = coordination.get_coordinator('zake://', b'host-1') coordinator.start() # Create a lock lock = coordinator.get_lock("foobar") with lock: print("Do something that is distributed") coordinator.stop()
tooz.coordination.CoordinationDriver.get_lock()
方法允许创建一个由名称标识的锁。 检索此锁之后,可以将其用作上下文管理器,或者使用 tooz.locking.Lock.acquire()
和 tooz.locking.Lock.release()
方法来获取和释放锁。
哈希环 (Hash ring)
Tooz提供了一致的哈希环实现。 它可以用于将对象(通过二进制键表示)映射到一个或多个节点。 当节点列表发生更改时,跨环的对象的重新平衡将保持最小。
from tooz import hashring hashring = hashring.HashRing({'node1', 'node2', 'node3'}) # Returns set(['node2']) nodes_for_foo = hashring[b'foo'] # Returns set(['node2', 'node3']) nodes_for_foo_with_replicas = hashring.get_nodes(b'foo', replicas=2) # Returns set(['node1', 'node3']) nodes_for_foo_with_replicas = hashring.get_nodes(b'foo', replicas=2, ignore_nodes={'node2'})
分区器(Partitioner)
Tooz基于其一致的散列环实现提供了一个partitioner对象。 它可以用于将Python对象映射到一个或多个节点。 partitioner对象自动跟踪加入和离开组的节点,从而管理重新平衡。
from tooz import coordination coordinator = coordination.get_coordinator('zake://', b'host-1') coordinator.start() partitioner = coordinator.join_partitioned_group("group1") # Returns {'host-1'} member = partitioner.members_for_object(object()) coordinator.leave_partitioned_group(partitioner) coordinator.stop()