基于LeaderSelector实现
当客户端成为Leader时,采用异步回调的方式调用takeLeadership,执行相应的逻辑;
优点如下:
1. 异步非阻塞;
2. 对于Leadership控制很灵活;
3. Leadership释放后可以重新排队竞争Leader;
4. 连接出现异常时,原先Leader正在执行的逻辑会被取消,防止出现并发;
/**
* 类说明:Leader选举客户端
*
* @author ruipeng.lrp
* @since 2017/10/19
**/
public class LeaderSelectorClient implements Closeable{
private static final String NAMESPACE = "dps";
private static final String LOCK_PATH = "/leader";
private CuratorFramework client;
private LeaderSelector leaderSelector;
private String connectString = "30.117.84.40:2181";
private int sessionTimeoutMs = 15*1000;
private int connectionTimeoutMs = 3*1000;
private String name;
public void init() throws Exception{
try{
client = CuratorFrameworkFactory.builder()
.connectString(this.connectString)
.sessionTimeoutMs(sessionTimeoutMs)
.connectionTimeoutMs(connectionTimeoutMs)
.retryPolicy(new ExponentialBackoffRetry(1000, 3)) //断连重试策略
.namespace(NAMESPACE) //应用隔离,相当于chroot
.build();
leaderSelector = new LeaderSelector(client, LOCK_PATH, Executors.newSingleThreadExecutor(), new LeaderSelectorListenerAdapter(){
@Override
public void takeLeadership(CuratorFramework client) throws Exception {
leaderAction();
}
});
leaderSelector.autoRequeue();
client.start();
leaderSelector.start();
}catch(Exception e){
CloseableUtils.closeQuietly(leaderSelector);
CloseableUtils.closeQuietly(client);
}
}
//成为leader后的业务逻辑
public void leaderAction() throws Exception{
while(true){
System.out.println(name + " is the leader");
Thread.sleep(1000);
}
}
@Override
public void close() throws IOException {
CloseableUtils.closeQuietly(leaderSelector);
CloseableUtils.closeQuietly(client);
System.out.println("shutting down...");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public static void main(String[] args) throws Exception {
LeaderSelectorClient c1 = new LeaderSelectorClient();
c1.init();
c1.setName("A1");
}
}
基于LeaderLatch实现
相当于分布式的CountDownLatch,阻塞等待直到成为leader,leadership释放后无法再次排队竞争leader;
public class LeaderLatchClient implements Closeable{
private static final String NAMESPACE = "dps";
private static final String LOCK_PATH = "/leader";
private CuratorFramework client;
private LeaderLatch leaderLatch;
private String connectString = "30.117.84.40:2181";
private int sessionTimeoutMs = 15*1000;
private int connectionTimeoutMs = 3*1000;
private String name;
public void init() throws Exception{
try{
client = CuratorFrameworkFactory.builder()
.connectString(this.connectString)
.sessionTimeoutMs(sessionTimeoutMs)
.connectionTimeoutMs(connectionTimeoutMs)
.retryPolicy(new ExponentialBackoffRetry(1000, 3)) //断连重试策略
.namespace(NAMESPACE) //应用隔离相当于chroot
.build();
leaderLatch = new LeaderLatch(client, LOCK_PATH);
client.start();
leaderLatch.start();
}catch(Exception e){
CloseableUtils.closeQuietly(leaderLatch);
CloseableUtils.closeQuietly(client);
}
}
//成为leader后的业务逻辑
public void leaderAction() throws Exception{
leaderLatch.await(); //阻塞等待成为leader
//持续关注leadership状态变更
while(leaderLatch.hasLeadership()){
System.out.println(name + " is the leader");
Thread.sleep(1000);
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public void close() throws IOException {
CloseableUtils.closeQuietly(leaderLatch);
CloseableUtils.closeQuietly(client);
}
public static void main(String[] args) throws Exception {
LeaderLatchClient c1 = new LeaderLatchClient();
c1.init();
c1.setName("A1");
c1.leaderAction();
}
}