选举我们在此文中只讲Curator的两个客户端的使用:
在分布式环境中,有时我们需要一个时间点只需要一个服务,如处理订单业务,一个订单过来,我们希望是的一个订单处理服务去处理这个业务,同时将处理的结果同步至其他的服务,保持主备机之间的同步性,因此需要一个主机,多个备机,当主机down掉之后,备机能随时启动保证服务继续运行;
1、Curator的选举代码应用
LeaderLatch 类
org.apache.curator.framework.recipes.leader.LeaderLatch
几个重要的方法
//开始进行抢主
void start()
//是否具有主权限
boolean hasLeadership()
//释放主权限
void close()
// 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.,
//-----尝试让实例获取leader权限,不一定成功,返回boolean
boolean await(long timeout, TimeUnit unit)
//是否抢主成功的一个监听
org.apache.curator.framework.recipes.leader.LeaderLatchListener
leaderLatch.addListener(new LeaderLatchListener() {
@Override
public void notLeader() {
System.out.println("没有获取领导权!");
}
@Override
public void isLeader() {
System.out.println("获取领导权!");
}
});
2、测试代码:
public class MasterLatch {
static int CLINET_COUNT = 10;
static String LOCK_PATH = "/leader_latch";
public static void main(String[] args) throws Exception {
List<CuratorFramework> clientsList = Lists.newArrayListWithCapacity(CLINET_COUNT);
List<LeaderLatch> leaderLatchList = Lists.newArrayListWithCapacity(CLINET_COUNT);
//创建10个zk客户端模拟leader选举
for (int i = 0; i < CLINET_COUNT; i++) {
CuratorFramework client = getZkClient();
clientsList.add(client);
LeaderLatch leaderLatch = new LeaderLatch(client, LOCK_PATH, "CLIENT_" + i);
leaderLatchList.add(leaderLatch);
leaderLatch.addListener(new LeaderLatchListener() {
@Override
public void notLeader() {
System.out.println("没有获取领导权!");
}
@Override
public void isLeader() {
System.out.println("获取领导权!");
}
});
//必须调用start()方法来进行抢主
leaderLatch.start();
}
//判断当前leader是哪个客户端
checkLeader(leaderLatchList);
}
private static void checkLeader(List<LeaderLatch> leaderLatchList) throws Exception {
//Leader选举需要时间 等待10秒
Thread.sleep(10000);
for (int i = 0; i < leaderLatchList.size(); i++) {
LeaderLatch leaderLatch = leaderLatchList.get(i);
//通过hasLeadership()方法判断当前节点是否是leader
if (leaderLatch.hasLeadership()) {
System.out.println("当前leader:"+leaderLatch.getId());
//释放leader权限 重新进行抢主
leaderLatch.close();
checkLeader(leaderLatchList);
}
}
}
private static CuratorFramework getZkClient() {
String zkServerAddress = "192.168.6.2:2181";
ExponentialBackoffRetry retryPolicy = new ExponentialBackoffRetry(1000, 3, 5000);
CuratorFramework zkClient = CuratorFrameworkFactory.builder()
.connectString(zkServerAddress)
.sessionTimeoutMs(5000)
.connectionTimeoutMs(5000)
.retryPolicy(retryPolicy)
.build();
zkClient.start();
return zkClient;
}
}
//LeaderLatch需要close后其他的线程才有机会获取leader权
3、 LeaderSelector应用
LeaderSelector类:
org.apache.curator.framework.recipes.leader.LeaderSelector
几个重要的方法:
//开始抢主
void start()
//释放主权后自动加入到抢主的行列
void autoRequeue()
//抢主的回调函数监听
LeaderSelectorListener
//抢主之后的逻辑处理
takeLeadership(CuratorFramework client) t
LeaderSelectorListenerAdapter
实现了接口监听与封装了客户端与zk服务器连接挂起或者断开时的处理逻辑(抛出抢主失败CancelLeadershipException)
4、代码上:
package com.tl.demo;
import java.util.List;
import org.apache.curator.RetryPolicy;
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.LeaderSelectorListener;
import org.apache.curator.framework.state.ConnectionState;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.curator.shaded.com.google.common.collect.Lists;
/**
* how to use LeaderSelector to implement master
*
*/
public class MasterLeaderSelector {
//设置客户端的数量
static int countClient=10;
//设置leader的路径
static String select_path="/selector";
public static void main(String[] args) {
List<CuratorFramework> clientList=Lists.newArrayListWithCapacity(countClient);
for(int i=0;i<countClient;i++) {
CuratorFramework client=getClient();
clientList.add(client);
LeaderSelector leaderSelector=new LeaderSelector(client,select_path,new LeaderSelectorListener() {
@Override
public void stateChanged(CuratorFramework client, ConnectionState newState) {
//失去连接是的状态
System.out.println("Client的连接状态发生变化");
}
@Override
public void takeLeadership(CuratorFramework client) throws Exception {
//抢主成功后的业务处理逻辑
System.out.println("获取leader的权利!");
}
});
//leaderSelector 释放leader后会自动加入到抢主的行列
leaderSelector.autoRequeue();
leaderSelector.start();
}
}
//create a client
private static CuratorFramework getClient() {
RetryPolicy policy=new ExponentialBackoffRetry(1000,3);
CuratorFramework curatorFramework= CuratorFrameworkFactory.builder().connectString("127.0.0.1:2181")
.sessionTimeoutMs(1000)
.connectionTimeoutMs(3000)
.retryPolicy(policy)
.build();
curatorFramework.start();
return curatorFramework;
}
}
实现 LeaderSelectorListenerAdapter
package com.tl.demo;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import org.apache.curator.RetryPolicy;
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;
import org.apache.curator.shaded.com.google.common.collect.Lists;
public class MasterLeaderSelectorListner {
//设置客户端的数量
static int countClient=10;
//设置leader的路径
static String select_path="/selector";
public static void main(String[] args) {
List<CuratorFramework> clientList=Lists.newArrayListWithCapacity(countClient);
for(int i=0;i<countClient;i++) {
CuratorFramework client=getClient();
clientList.add(client);
SelectorClient leaderSelector =new SelectorClient(client,select_path,"client"+i);
//leaderSelector 释放leader后会自动加入到抢主的行列
leaderSelector.start();
}
}
static class SelectorClient extends LeaderSelectorListenerAdapter implements Cloneable{
String nameString;
LeaderSelector selector;
public SelectorClient(CuratorFramework client, String path, String name) {
nameString=name;
selector=new LeaderSelector(client, path, this);
selector.autoRequeue();
}
@Override
public void takeLeadership(CuratorFramework client) throws Exception {
//run waittime off leader
final int waitTime=(int)(5*Math.random())+1;
Thread.sleep(TimeUnit.SECONDS.toMillis(waitTime));
}
public void start() {
selector.start();
}
public void close() {
selector.close();
}
}
//create a client
private static CuratorFramework getClient() {
RetryPolicy policy=new ExponentialBackoffRetry(1000,3);
CuratorFramework curatorFramework= CuratorFrameworkFactory.builder().connectString("127.0.0.1:2181")
.sessionTimeoutMs(1000)
.connectionTimeoutMs(3000)
.retryPolicy(policy)
.build();
curatorFramework.start();
return curatorFramework;
}
}
两种方法:
第一种:LeaderLatch需要使用方法close才能释放leader的权限
第二种:推荐使用具有自主释放的额权利,与平等竞争leader的权利