- 模擬多臺服務器
package com.uinnova.ftpsynweb.zookeeper.zkclient;
import java.io.Serializable;
/**
* @author xuyangyang
*/
public class UserCenter implements Serializable {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "UserCenter{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
- 開始選主
package com.uinnova.ftpsynweb.zookeeper.zkclient;
import org.I0Itec.zkclient.IZkDataListener;
import org.I0Itec.zkclient.ZkClient;
import org.I0Itec.zkclient.exception.ZkNodeExistsException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* @author xuyangyang
*/
public class MasterSelector {
public static final String MASTER_PATH = "/master";
private ZkClient zkClient;
private UserCenter master;
private UserCenter server;
private IZkDataListener dataListener;
private boolean isRunning = false;
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
public MasterSelector(ZkClient zkClient, UserCenter server) {
System.out.println("[" + server + "]" + "去爭搶master權限");
this.server = server;
this.zkClient = zkClient;
this.dataListener = new IZkDataListener() {
@Override
public void handleDataChange(String s, Object o) throws Exception {
}
@Override
public void handleDataDeleted(String s) throws Exception {
//節點如果被刪除,會觸發選主操作
chooseMaster();
}
};
}
public void start() {
if (!isRunning) {
isRunning = true;
zkClient.subscribeDataChanges(MASTER_PATH, dataListener);
chooseMaster();
}
}
public void stop() {
if (isRunning) {
isRunning = false;
scheduledExecutorService.shutdown();
zkClient.unsubscribeDataChanges(MASTER_PATH, dataListener);
releaseMaster();
}
}
private void chooseMaster() {
if (!isRunning) {
System.out.println("當前服務沒有啓動");
return;
}
try {
zkClient.createEphemeral(MASTER_PATH, server);
master = server;
System.out.println(server + "我現在已經是master了,你們要聽我的");
// 定時器,定時釋放(模擬master出現故障)
scheduledExecutorService.schedule(() -> {
releaseMaster();
}, 2, TimeUnit.SECONDS);
} catch (ZkNodeExistsException e) {
//標識master已經存在
UserCenter userCenter = zkClient.readData(MASTER_PATH, true);
if (userCenter == null) {
System.out.println("啓動操作");
chooseMaster();
} else {
master = userCenter;
}
}
}
private void releaseMaster() {
if (checkIsMaster()) {
zkClient.delete(MASTER_PATH);
}
}
private boolean checkIsMaster() {
UserCenter userCenter = zkClient.readData(MASTER_PATH);
if (userCenter.getName().equals(server.getName())) {
return true;
}
return false;
}
}
- 測試選主
package com.uinnova.ftpsynweb.zookeeper.zkclient;
import org.I0Itec.zkclient.ZkClient;
import org.I0Itec.zkclient.serialize.SerializableSerializer;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;
/**
* 測試zookeeper master選主
*
* @author xuyangyang
*/
public class MasterChooseTest {
public final static String IP = "140.143.236.197:2181";
public static void main(String[] args) {
ArrayList<MasterSelector> masterSelectors = new ArrayList<>();
try {
for (int i = 0; i < 10; i++) {
ZkClient zkClient = new ZkClient(IP, 50000, 50000, new SerializableSerializer());
UserCenter userCenter = new UserCenter();
userCenter.setId(i);
userCenter.setName("我的名字" + i);
MasterSelector masterSelector = new MasterSelector(zkClient, userCenter);
masterSelectors.add(masterSelector);
masterSelector.start();
TimeUnit.SECONDS.sleep(2);
}
} catch (InterruptedException e) {
masterSelectors.forEach((selector) -> {
selector.stop();
});
}
}
}
- 測試結果
[UserCenter{id=0, name='我的名字0'}]去爭搶master權限
UserCenter{id=0, name='我的名字0'}我現在已經是master了,你們要聽我的
UserCenter{id=0, name='我的名字0'}我現在已經是master了,你們要聽我的
UserCenter{id=0, name='我的名字0'}我現在已經是master了,你們要聽我的
UserCenter{id=0, name='我的名字0'}我現在已經是master了,你們要聽我的
UserCenter{id=0, name='我的名字0'}我現在已經是master了,你們要聽我的
UserCenter{id=0, name='我的名字0'}我現在已經是master了,你們要聽我的
[UserCenter{id=1, name='我的名字1'}]去爭搶master權限
啓動操作
UserCenter{id=1, name='我的名字1'}我現在已經是master了,你們要聽我的
UserCenter{id=1, name='我的名字1'}我現在已經是master了,你們要聽我的
UserCenter{id=1, name='我的名字1'}我現在已經是master了,你們要聽我的
UserCenter{id=1, name='我的名字1'}我現在已經是master了,你們要聽我的
UserCenter{id=1, name='我的名字1'}我現在已經是master了,你們要聽我的
UserCenter{id=1, name='我的名字1'}我現在已經是master了,你們要聽我的
[UserCenter{id=2, name='我的名字2'}]去爭搶master權限
UserCenter{id=1, name='我的名字1'}我現在已經是master了,你們要聽我的
UserCenter{id=1, name='我的名字1'}我現在已經是master了,你們要聽我的
UserCenter{id=1, name='我的名字1'}我現在已經是master了,你們要聽我的
UserCenter{id=1, name='我的名字1'}我現在已經是master了,你們要聽我的
UserCenter{id=1, name='我的名字1'}我現在已經是master了,你們要聽我的
[UserCenter{id=3, name='我的名字3'}]去爭搶master權限
UserCenter{id=2, name='我的名字2'}我現在已經是master了,你們要聽我的
UserCenter{id=3, name='我的名字3'}我現在已經是master了,你們要聽我的
UserCenter{id=3, name='我的名字3'}我現在已經是master了,你們要聽我的
UserCenter{id=1, name='我的名字1'}我現在已經是master了,你們要聽我的
UserCenter{id=3, name='我的名字3'}我現在已經是master了,你們要聽我的
UserCenter{id=3, name='我的名字3'}我現在已經是master了,你們要聽我的
[UserCenter{id=4, name='我的名字4'}]去爭搶master權限
UserCenter{id=1, name='我的名字1'}我現在已經是master了,你們要聽我的
UserCenter{id=3, name='我的名字3'}我現在已經是master了,你們要聽我的
UserCenter{id=3, name='我的名字3'}我現在已經是master了,你們要聽我的
UserCenter{id=1, name='我的名字1'}我現在已經是master了,你們要聽我的
UserCenter{id=3, name='我的名字3'}我現在已經是master了,你們要聽我的
[UserCenter{id=5, name='我的名字5'}]去爭搶master權限
UserCenter{id=3, name='我的名字3'}我現在已經是master了,你們要聽我的
UserCenter{id=5, name='我的名字5'}我現