Curator-Recipes-Elections使用(四)

摘要

Curator实现了全部Zookeeper的食谱方法(除了两阶段提交)。NOTE: Most Curator recipes will autocreate parent nodes of paths given to the recipe as CreateMode.CONTAINE。

选举

在分布式计算中,Leader选举是指在分布式的多个计算机节点中选出一个组织者或者领导者的过程。在任务开始之前,所有网络节点都不知道那个节点会成为Leader。一旦选举后,每个节点都将一个独有的唯一的节点作为领导者。

选举机制有两种方式,根据业务场景,选择即可。下面分别介绍:

Leader Latch

用法

创建LeaderLatch实例

1
2
3
4
public LeaderLatch(CuratorFramework client,String latchPath)
Parameters:
client - the client
latchPath - the path for this leadership group
1
2
3
4
5
public LeaderLatch(CuratorFramework client,String latchPath,String id)
Parameters:
client - the client
latchPath - the path for this leadership group
id - participant ID

然后调用start()启动

1
leaderLatch.start();

一旦启动,LeaderLatch就会跟所有使用相同latchPath的参与谈判,随机的选一个成为leader,另外,你可以任何时候通过下面方法判断当前实例是否是Leader。

1
2
public boolean hasLeadership()
Return true if leadership is currently held by this instance

与JDK的CountDownLatch相似,LeaderLatch 也会block进程,直到获取leadership。

1
2
3
4
5
public void await()
throws InterruptedException,
EOFException
Causes the current thread to wait until this instance acquires leadership
unless the thread is interrupted or closed.

当前线程会被阻塞,两种方式退出:1、获得leadership,2、被中断。

1
2
3
4
5
6
7
8
9
10
11
12
public boolean await(long timeout,
TimeUnit unit)
throws InterruptedException
Causes the current thread to wait until this instance acquires leadership unless
the thread is interrupted, the specified waiting time elapses or the instance is closed.

Parameters:
timeout - the maximum time to wait
unit - the time unit of the timeout argument
Returns:
true if the count reached zero and false if the waiting time elapsed before the count
reached zero or the instances was closed

当前线程会被阻塞,三种方式退出:1、获得leadership,2、未超时被中断,3,等待时间超时。

当通过或者完成使用LeaderLatch实例时,你必须关闭实例,这样假如实例是Leader,会释放Leader权限,其他参与的节点会被选为新的Leader。

leaderLatch.close();

错误处理机制

LeaderLatch 实例增加一个ConnectionStateListener监听连接问题。如果发现SUSPENDED或者LOST,LeaderLatch的领导者会报告说他不在是领导者(在重新连接之前不会是Leader)。如果丢失的连接重新连接了恩,LeaderLatch会删除它之前的节点,并创建一个新的节点。

LeaderLatch的用户必须要考虑到连接问题回调熬着领导权的丢失问题,比如hasLeadership()返回true,但是一段时间后,连接挂起后者丢失,那时,hasLeadership将会返回false。所以强烈建议LeaderLatch用户注册一个ConnectionStateListener。这里LeaderLatch已经都做了。不需要用户单独处理。

Leader Election

用法

创建一个 LeaderSelector

1
2
3
4
5
6
7
public LeaderSelector(CuratorFramework client,
String mutexPath,
LeaderSelectorListener listener)
Parameters:
client - the client
mutexPath - the path for this leadership group
listener - listener
1
2
3
4
5
6
7
8
9
10
11
public LeaderSelector(CuratorFramework client,
String mutexPath,
ThreadFactory threadFactory,
Executor executor,
LeaderSelectorListener listener)
Parameters:
client - the client
mutexPath - the path for this leadership group
threadFactory - factory to use for making internal threads
executor - the executor to run in
listener - listener

LeaderSelectors 需要启动:

1
leaderSelector.start();

Once started, the takeLeadership() of your listener will be called when you have leadership. Your takeLeadership() method should only return when leadership is being relinquished.

一旦启动,当这个节点获取领导权,监听里面takeLeadership()会被调用。并且,takeLeadership()方法需要阻塞,直到领导权被放弃,才能返回。也就是说:你不想让实例丢失领导权,takeLeadership()就要阻塞不能返回(死循环也行)。

当通过LeaderSelector实例,还要调用close,关闭。

1
leaderSelector.close();

错误处理机制

LeaderSelectorListener类是继承ConnectionStateListener的。当LeaderSelector启动,它就注册监听到Curator实例上了。使用LeaderSelector的用户必须关注任何的连接状态的改变。如果一个实例成为领导者,它应该响应被挂起或丢失的通知。如果被报告是SUSPENDED状态,当前实例就要假设自己已经不是Leader了,直到收到RECONNECTED状态,如果报告了LOST状态,这个实例就不再是Leader,并且它的takeLeadership方法就要放回了。

重要提示:当接收到SUSPENDED或者LOST的时候,建议操作是抛出CancelLeadershipException。这样讲使得LeaderSelector实例试着去打断并取消正在执行takeLeadership方法的线程。因为这个非常重要,你可以考虑扩展用LeaderSelectorListenerAdapter,当然LeaderSelectorListenerAdapter已经为你写好推荐的处理方式。

区别与联系

和LeaderLatch的区别, LeaderSelector通过LeaderSelectorListener可以对领导权进行控制, 在适当的时候释放领导权,这样每个节点都有可能获得领导权。 而LeaderLatch一根筋到死, 除非调用close方法,否则它不会释放领导权。

另外设置leaderSelector.autoRequeue();可以保证在此实例释放领导权之后还可能获得领导权。

例子:https://github.com/liuhailin/apache-curator-course/tree/master/chapter-2

坚持技术分享,您的支持将鼓励我继续创作!