版本依赖:
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>2.10.0</version>
</dependency>
示例一:
package com.zk.leader;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.leader.LeaderLatch;
import org.apache.curator.retry.ExponentialBackoffRetry;
/**
* 必须启动LeaderLatch: leaderLatch.start();
* 一旦启动, LeaderLatch会和其它使用相同latch path的其它LeaderLatch交涉,然后随机的选择其中一个作为leader。
* 你可以随时查看一个给定的实例是否是leader:
*/
public class Example1
{
private static final String PATH = "/leader";
private static final int COUNT = 5;
public static void main(String[] args) throws Exception
{
CuratorFramework client = CuratorFrameworkFactory.newClient("192.168.1.100:2181", new ExponentialBackoffRetry(1000, 3));
client.start();
List<LeaderLatch> list = new ArrayList<>();
for (int i = 1; i <= COUNT; i++)
{
LeaderLatch example = new LeaderLatch(client, PATH, "Client #" + i);
example.start();
list.add(example);
}
TimeUnit.SECONDS.sleep(2);
LeaderLatch leader = null;
for (LeaderLatch ll : list)
{
if (ll.hasLeadership())
{
leader = ll;
}
System.out.println(ll.getId() + "\t" + ll.hasLeadership());
}
;
TimeUnit.SECONDS.sleep(2);
list.remove(leader);
leader.close();
TimeUnit.SECONDS.sleep(2);
System.out.println("========================");
for (LeaderLatch ll : list)
{
System.out.println(ll.getId() + "\t" + ll.hasLeadership());
}
for (LeaderLatch ll : list)
{
ll.close();
}
client.close();
}
}
输出如下:
Client #1 false
Client #2 false
Client #3 true
Client #4 false
Client #5 false
========================
Client #1 false
Client #2 false
Client #4 false
Client #5 true
示例二:
package com.zk.leader;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.leader.LeaderSelector;
import org.apache.curator.framework.recipes.leader.LeaderSelectorListenerAdapter;
import org.apache.curator.retry.ExponentialBackoffRetry;
/**
* 与LeaderLatch相比, 通过LeaderSelectorListener可以对领导权进行控制, 在适当的时候释放领导权,这样每个节点都有可能获得领导权。
* 而LeaderLatch一根筋到死, 除非调用close方法,否则它不会释放领导权。
*/
public class Example2
{
private static final String PATH = "/leader";
private static final int COUNT = 5;
public static void main(String[] args) throws Exception
{
CuratorFramework client = CuratorFrameworkFactory.newClient("192.168.1.100:2181", new ExponentialBackoffRetry(1000, 3));
client.start();
List<MyLeaderSelectorListenerAdapter> list = new ArrayList<>();
for (int i = 1; i <= COUNT; i++)
{
MyLeaderSelectorListenerAdapter example = new MyLeaderSelectorListenerAdapter(client, PATH, "Client #" + i);
list.add(example);
}
TimeUnit.SECONDS.sleep(20);
for (MyLeaderSelectorListenerAdapter listener : list)
{
listener.close();
}
client.close();
}
}
class MyLeaderSelectorListenerAdapter extends LeaderSelectorListenerAdapter
{
private final String name;
private final LeaderSelector leaderSelector;
public MyLeaderSelectorListenerAdapter(CuratorFramework client, String path, String name)
{
this.name = name;
leaderSelector = new LeaderSelector(client, path, this);
//保证在此实例释放领导权之后还可能获得领导权。
leaderSelector.autoRequeue();
leaderSelector.start();
}
public void close()
{
leaderSelector.close();
}
/**
* 你可以在takeLeadership进行任务的分配等等,并且不要返回,如果你想要要此实例一直是leader的话可以加一个死循环。
* 一旦此方法执行完毕之后,就会重新选举
*/
public void takeLeadership(CuratorFramework client) throws Exception
{
System.out.println(name + " 当选为leader");
TimeUnit.SECONDS.sleep(2);
}
}
输出如下:
Client #1 当选为leader
Client #4 当选为leader
Client #2 当选为leader
Client #3 当选为leader
Client #5 当选为leader
Client #1 当选为leader
Client #4 当选为leader
Client #2 当选为leader
Client #3 当选为leader
Client #5 当选为leader
以上是使用curator实现leader的两种方法