Curator实现简单的master选举
1.在zookeeper服务器上创建一个节点用于存储master服务器地址
2.若master服务器宕机,则删除master节点,同时发送消息给所有服务器开始争抢新一轮的master
3.所有服务器开始在zookeeper服务器上创建master节点,master节点数据内容为当前争抢的服务器地址
4.若有服务器成功第一个创建master节点则此服务器为master
5.之后的服务器创建master节点会提示节点已存在,则获取master节点数据,记录下新一轮的master服务器地址
6.为防止网络抖动,可以在每次争抢master时优先让上一轮的master服务器创建master节点
public class RunningData implements Serializable {
/**
*
*/
private static final long serialVersionUID = 5782460288263167189L;
private Long cid;
private String name;
public Long getCid() {
return cid;
}
public void setCid(Long cid) {
this.cid = cid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class WorkServer {
private volatile boolean running = false;//记录服务器的状态
private static final String MASTER_PATH = "/master";
private static final String SERVER_IP = "192.168.0.3:2181";
private PathChildrenCache cache;
private CuratorFramework client;
private RunningData serverData; //记录当前服务器基本信息
private RunningData masterData = new RunningData();//记录集群中master的基本信息
private ScheduledExecutorService delayExecutor = Executors.newScheduledThreadPool(1);
private int delayTime = 5;
public WorkServer(RunningData rd) throws Exception {
this.serverData = rd;
}
public void start() throws Exception {
if(running) {
throw new Exception("server has startup...");
}
running = true;
RetryPolicy retry = new ExponentialBackoffRetry(1000, 3);
client = CuratorFrameworkFactory.newClient(SERVER_IP, 5000, 5000, retry);
client.start();
cache = new PathChildrenCache(client,MASTER_PATH,true);
cache.start();
cache.getListenable().addListener(new PathChildrenCacheListener() {
@Override
public void childEvent(CuratorFramework curator, PathChildrenCacheEvent event) throws Exception {
switch (event.getType()) {
case CHILD_ADDED:
break;
case CHILD_UPDATED:
break;
case CHILD_REMOVED:
takeMaster();
//防止网络抖动选出来的master和上一次master一样
//System.out.println("remove");
/*if(masterData != null && masterData.getName().equals(serverData.getName())) {//当前服务器是上次master
takeMaster();
}
else{
delayExecutor.schedule(new Runnable(){//否则延迟5秒争抢master
@Override
public void run() {
try {
takeMaster();
} catch (Exception e) {
e.printStackTrace();
}
}
}, delayTime, TimeUnit.SECONDS);
}*/
break;
default:
break;
}
}
});
//System.out.println("now start:" + serverData.getCid());
takeMaster();
}
public void stop() throws Exception {
if(!running) {
throw new Exception("server has stoped!");
}
running = false;
releaseMaster();
client.close();
}
/*
* 争抢master
*/
private void takeMaster() throws Exception {
if(!running) {
return;
}
//System.out.println("now takemaster:" + serverData.getCid());
try {
Long cid = serverData.getCid();
String s = String.valueOf(cid);
client.create().creatingParentsIfNeeded().withMode(CreateMode.EPHEMERAL).forPath(MASTER_PATH+MASTER_PATH,s.getBytes());
masterData.setCid(serverData.getCid());
masterData.setName(serverData.getName());
System.out.println("master is " + masterData.getName());
//测试代码
delayExecutor.schedule(new Runnable(){
@Override
public void run() {
try {
releaseMaster();
}catch(Exception e) {
e.printStackTrace();
}
}
}, delayTime, TimeUnit.SECONDS);
}catch(NodeExistsException e) {
byte[] bytes1 = client.getData().forPath(MASTER_PATH+MASTER_PATH);
String s = new String(bytes1);
if(bytes1 == null) {
takeMaster();
}else {
if(!s.equals("")){
Long cid = Long.valueOf(s);
masterData.setCid(cid);
masterData.setName("client: " + cid);
//System.out.println("now ok:" + serverData.getCid());
}
}
}
}
/*
* 释放master权利
*/
private void releaseMaster() throws Exception {
if(checkMaster()) {
client.delete().guaranteed().deletingChildrenIfNeeded().forPath(MASTER_PATH);
}
}
/*
* 检测自己是否为Master
*/
private boolean checkMaster() {
try{
byte[] bytes = client.getData().forPath(MASTER_PATH+MASTER_PATH);
String s = new String(bytes);
if(!s.equals("")) {
Long cid = Long.valueOf(s);
if(serverData.getCid().equals(cid)) {
return true;
}
}
} catch(NoNodeException e1) {
return false;
} catch(InterruptedException e2) {
return checkMaster();
} catch(Exception e) {
System.out.println("translation" + e.getMessage());
e.printStackTrace();
}
return false;
}
}
启动:
public class LeaderSelector {
//启动服务个数
private static final int CLIENT_QTY = 4;
private static final String SERVER_IP = "192.168.0.3:2181";
public static void main(String[] args) throws Exception {
List<WorkServer> workServers = new ArrayList<>();
try {
/*RetryPolicy retry = new ExponentialBackoffRetry(1000, 3);
CuratorFramework client = CuratorFrameworkFactory.newClient(SERVER_IP, 5000, 5000, retry);
client.start();
Thread.sleep(5000);*/
for(int i=1; i<=CLIENT_QTY; i++) {
RunningData runningData = new RunningData();
runningData.setCid(Long.valueOf(i));
runningData.setName("client: " + i);
WorkServer workServer = new WorkServer(runningData);
workServer.start();
workServers.add(workServer);
}
Thread.sleep(Integer.MAX_VALUE);
}catch(Exception e){
e.printStackTrace();
}finally {
System.out.println("Shutdown。。。");
for(WorkServer workServer : workServers) {
try{
workServer.stop();
System.out.println("close");
}catch(Exception e1) {
e1.printStackTrace();
}
}
}
}
}
console:
master is client: 1
master is client: 1
master is client: 2
master is client: 3
master is client: 1
master is client: 1
master is client: 1