04zookeeper场景应用-master选举
生活随笔
收集整理的這篇文章主要介紹了
04zookeeper场景应用-master选举
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
master選舉
考慮到7x24向外提供服務的系統,不能有單點故障,于是我們使用集群,采用的是master-salve模式。集群中有一臺主機和多臺備機,其中主機向外提供服務,備機監聽主機狀態,一旦主機宕機,備機必須迅速接管主機繼續向外提供服務。在這個過程中,從備機中選出一臺作為主機的過程稱為master選舉
架構圖
左邊是zookeeper集群,右邊是工作服務器。工作服務器啟動的時候會去zookeeper的servers節點下進行創建臨時節點,并把基本信息寫入節點。這個過程叫做服務注冊。系統中的其他服務可以通過獲取servers節點下所有的自節點可以得知當前系統有哪些服務可用,這個過程叫做服務發現。接著這些工作服務器會嘗試創建一個master節點,誰創建成功誰就是master其余的節點就是salve。同時所有的服務器必須監聽master節點的刪除事件。通過監聽master節點的刪除事件,來了解master節點是否宕機。一旦master宕機開始新一輪的master選舉。
流程圖
核心類圖
WorkServer對應架構圖的WorkServer,是主工作類;
RunningData用來描述WorkServer的基本信息;
LeaderSelectorZkClient作為調度器來啟動和停止WorkServer;
代碼實現
/*** Created by zhangdd on 2019/12/17* <p>* 工作服務器信息*/ public class RunningData implements Serializable {private static final long serialVersionUID = 4478643441552034827L;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;} } /*** Created by zhangdd on 2019/12/17* <p>* 工作服務器*/ public class WorkServer {// 記錄服務器狀態private volatile boolean running = false;private ZkClient zkClient;// Master節點對應zookeeper中的節點路徑private static final String MASTER_PATH = "/master";// 監聽Master節點刪除事件private IZkDataListener dataListener;// 記錄當前節點的基本信息private RunningData serverData;// 記錄集群中Master節點的基本信息private RunningData masterData;private ScheduledExecutorService delayExector = Executors.newScheduledThreadPool(1);private int delayTime = 5;public WorkServer(RunningData rd) {//注冊server節點//嘗試寫master節點,this.serverData = rd;this.dataListener = new IZkDataListener() {@Overridepublic void handleDataChange(String s, Object o) throws Exception {}@Overridepublic void handleDataDeleted(String s) throws Exception { // if (masterData != null && masterData.getName().equals(serverData.getName())) { // // 自己就是上一輪的Master服務器,則直接搶 // takeMaster(); // } else {// 否則,延遲5秒后再搶。主要是應對網絡抖動,給上一輪的Master服務器優先搶占master的權利,避免不必要的數據遷移開銷delayExector.schedule(new Runnable() {public void run() {takeMaster();}}, delayTime, TimeUnit.SECONDS); // }}};}public ZkClient getZkClient() {return zkClient;}public void setZkClient(ZkClient zkClient) {this.zkClient = zkClient;}// 停止服務器public void stop() throws Exception {if (!running) {throw new Exception("server has stoped");}running = false;delayExector.shutdown();// 取消Master節點事件訂閱zkClient.unsubscribeDataChanges(MASTER_PATH, dataListener);// 釋放Master權利releaseMaster();}public void start() throws Exception {if (running) {throw new Exception("server has start up ...");}running = true;//訂閱master刪除事件zkClient.subscribeDataChanges(MASTER_PATH, dataListener);//爭搶master權利takeMaster();}private void takeMaster() {if (!running) {return;}try {zkClient.createEphemeral(MASTER_PATH, serverData);masterData = serverData;System.out.println("我是 "+serverData.getName() + " 我搶到了 master");//作為演示,這里讓master服務器每隔5秒釋放一次Master權利delayExector.schedule(new Runnable() {@Overridepublic void run() {if (checkMaster()) {System.out.println("我是master " + masterData.getName() + " 我要銷毀了 你們準備好搶奪啊");releaseMaster();}}}, 5, TimeUnit.SECONDS);} catch (ZkNodeExistsException e) {//節點已經存在 // System.out.println(e.getMessage() + "\n" + serverData.getName());//讀取Master節點信息RunningData runningData = zkClient.readData(MASTER_PATH);if (runningData == null) {takeMaster(); // 沒讀到,讀取瞬間Master節點宕機了,有機會再次爭搶} else {masterData = runningData;}} catch (Exception e) {e.printStackTrace();}}// 釋放Master權利private void releaseMaster() {if (checkMaster()) {zkClient.delete(MASTER_PATH);}}/*** 檢測當前是否是master** @return*/private boolean checkMaster() {try {RunningData eventData = zkClient.readData(MASTER_PATH);masterData = eventData;if (masterData.getName().equals(serverData.getName())) {return true;}return false;} catch (Exception e) {return false;}} } /*** Created by zhangdd on 2019/12/17* <p>* 調度器*/ public class LeaderSelectorZkClient {//啟動的服務個數private static final int CLIENT_QTY = 10;//zookeeper服務器的地址private static final String ZOOKEEPER_SERVER = "192.168.0.119:2181";public static void main(String[] args) {//保存所有zkClient的列表List<ZkClient> clients = new ArrayList<>();//保存所有服務的列表List<WorkServer> workServers = new ArrayList<WorkServer>();try {for (int i = 0; i < CLIENT_QTY; i++) {//創建zkclientZkClient zkClient = new ZkClient(ZOOKEEPER_SERVER, 5000, 5000, new SerializableSerializer());clients.add(zkClient);RunningData runningData = new RunningData();runningData.setCid(Long.valueOf(i));runningData.setName("Client #" + i);//創建服務WorkServer workServer = new WorkServer(runningData);workServer.setZkClient(zkClient);workServers.add(workServer);workServer.start();}System.out.println("敲入回車鍵退出 \n");new BufferedReader(new InputStreamReader(System.in)).readLine();} catch (Exception e) {e.printStackTrace();} finally {System.out.println("Shutting down...");for (int i = 0; i < workServers.size(); i++) {try {workServers.get(i).stop();} catch (Exception e) {e.printStackTrace();}}for (int i = 0; i < clients.size(); i++) {try {clients.get(i).close();} catch (Exception e) {e.printStackTrace();}}}} }總結
以上是生活随笔為你收集整理的04zookeeper场景应用-master选举的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: win8 磁贴
- 下一篇: 离职前需要注意的事情?