基于库zkclient 的leader选举代码实现
利用了zookeeper临时节点,在当连接或session断掉时被删除这一特性来做选举。(简单简单互斥锁)
查了下网上的做法。
大致流程:
<1>判定是否存在/wzgtest路径
<2>如果不存在,那么试图创建一个节点znode(Ephemeral Path)(path = /wzgtest,data=client id)
<2.1>创建成功,标识自己是leader。
<2.2>创建不成功(包括异常)标识自己是slave。
<3>监听/wzgtest节点的数据变化。节点移除(zookeeper连接断开,session超时)时,重走<1>重新进行选举。
具体代码详见附件。
该代码只是实现,并未进行包装优化。
1 import java.net.InetAddress; 2 import java.net.UnknownHostException; 3 4 import org.I0Itec.zkclient.IZkDataListener; 5 import org.I0Itec.zkclient.ZkClient; 6 7 /** 8 * @author 作者 王志刚 9 * @version 创建时间:2016年8月18日 下午7:13:49 10 * @Description: zkleader选举 11 */ 12 public class ZKLeaderElect { 13 14 public boolean isLeader = false; 15 private ZkClient zkClient = null; 16 private String path = "XXXXX"; 17 private String hostInfo = "initString"; 18 19 public void initZKLeaderElect(String zkServers, String path, String s) { 20 zkClient = new ZkClient(zkServers, 10000, 10000); 21 this.path = path; 22 try { 23 hostInfo = InetAddress.getLocalHost().toString(); 24 } catch (UnknownHostException e) { 25 } 26 hostInfo = s; 27 } 28 29 /** 30 * 选举leader 31 * 32 */ 33 public void tryLeader() { 34 if (!zkClient.exists(path)) { 35 try { 36 zkClient.createEphemeral(path, hostInfo); 37 isLeader = true; 38 System.out.println(hostInfo + " 成为leader了"); 39 } catch (Exception e) { 40 System.out.println(hostInfo+"成为leader失败"); 41 e.printStackTrace(); 42 isLeader = false; 43 } 44 } 45 } 46 47 /** 48 * 监听指定节点的数据变化 49 * 50 */ 51 public void testListener() throws InterruptedException { 52 // 监听指定节点的数据变化 53 zkClient.subscribeDataChanges(path, new IZkDataListener() { 54 public void handleDataChange(String s, Object o) throws Exception { 55 // System.out.println(hostInfo+"说:"); 56 // System.out.println("node data changed!"); 57 // System.out.println("node=>" + s); 58 // System.out.println("data=>" + o); 59 // System.out.println("--------------"); 60 // tryLeader(); 61 } 62 63 public void handleDataDeleted(String s) throws Exception { 64 System.out.println(hostInfo+"说:"); 65 System.out.println("node data deleted!"); 66 System.out.println("s=>" + s); 67 System.out.println("--------------"); 68 tryLeader(); 69 } 70 }); 71 72 System.out.println(hostInfo + " ----- ready!"); 73 74 } 75 76 public static void main(String[] args) throws InterruptedException { 77 ZKLeaderElect zk1 = new ZKLeaderElect(); 78 zk1.initZKLeaderElect("10.1.51.221:7605", "/wzgtest","1"); 79 80 ZKLeaderElect zk2 = new ZKLeaderElect(); 81 zk2.initZKLeaderElect("10.1.51.221:7605", "/wzgtest","2"); 82 83 ZKLeaderElect zk3 = new ZKLeaderElect(); 84 zk3.initZKLeaderElect("10.1.51.221:7605", "/wzgtest","3"); 85 86 zk1.tryLeader(); 87 zk2.tryLeader(); 88 zk3.tryLeader(); 89 zk1.testListener(); 90 zk2.testListener(); 91 zk3.testListener(); 92 int i = 0; 93 // junit测试时,防止线程退出 94 while (true) { 95 Thread.sleep(1000); 96 i++; 97 if(i % 5 == 0){ 98 if(zk1.isLeader){ 99 zk1.zkClient.close(); 100 System.out.println("1 关闭了"); 101 zk1.isLeader = false; 102 } 103 if(zk2.isLeader){ 104 zk2.zkClient.close(); 105 System.out.println("2 关闭了"); 106 zk2.isLeader = false; 107 } 108 if(zk3.isLeader){ 109 zk3.zkClient.close(); 110 System.out.println("3 关闭了"); 111 zk3.isLeader = false; 112 } 113 } 114 System.out.println("1"+zk1.isLeader+" 2:"+zk2.isLeader+" 3:"+zk3.isLeader); 115 116 } 117 } 118 }