zookeeper的命名服务有两个应用方向,一个是提供类似JNDI的功能,利用zookeepeer的树型分层结构,可以把系统中各种服务的名称、地址以及目录信息存放在zookeeper,需要的时候去zookeeper中读取。
另一个,是利用zookeeper顺序节点的特性,制作分布式的ID生成器,写过数据库应用的朋友都知道,我们在往数据库表中插入记录时,通常需要为该记录创建唯一的ID,在单机环境中我们可以利用数据库的主键自增功能。但在分布式环境则无法使用,有一种方式可以使用UUID,但是它的缺陷是没有规律,很难理解。利用zookeeper顺序节点的特性,我们可以生成有顺序的,容易理解的,同时支持分布式环境的序列号。
代码实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
| public class IdMaker {
private ZkClient client = null; private final String server; private final String root; private final String nodeName; private volatile boolean running = false; private ExecutorService cleanExector = null; public enum RemoveMethod{ NONE,IMMEDIATELY,DELAY } public IdMaker(String zkServer,String root,String nodeName){ this.root = root; this.server = zkServer; this.nodeName = nodeName; }
public void start() throws Exception { if (running) throw new Exception("server has stated..."); running = true; init(); } public void stop() throws Exception { if (!running) throw new Exception("server has stopped..."); running = false; freeResource(); } private void init(){ client = new ZkClient(server,5000,5000,new BytesPushThroughSerializer()); cleanExector = Executors.newFixedThreadPool(10); try{ client.createPersistent(root,true); }catch (ZkNodeExistsException e){ } }
private void freeResource(){
cleanExector.shutdown(); try{ cleanExector.awaitTermination(2, TimeUnit.SECONDS); }catch(InterruptedException e){ e.printStackTrace(); }finally{ cleanExector = null; } if (client!=null){ client.close(); client=null; } }
private void checkRunning() throws Exception { if (!running) throw new Exception("请先调用start"); }
private String ExtractId(String str){ int index = str.lastIndexOf(nodeName); if (index >= 0){ index+=nodeName.length(); return index <= str.length()?str.substring(index):""; } return str; }
public String generateId(RemoveMethod removeMethod) throws Exception{ checkRunning();
final String fullNodePath = root.concat("/").concat(nodeName); final String ourPath = client.createPersistentSequential(fullNodePath, null);
if (removeMethod.equals(RemoveMethod.IMMEDIATELY)){ client.delete(ourPath); }else if (removeMethod.equals(RemoveMethod.DELAY)){ cleanExector.execute(new Runnable() { public void run() { client.delete(ourPath); } }); } return ExtractId(ourPath); }
} public class TestIdMaker {
public static void main(String[] args) throws Exception { IdMaker idMaker = new IdMaker("192.168.1.105:2181", "/NameService/IdGen", "ID"); idMaker.start();
try { for (int i = 0; i < 10; i++) { String id = idMaker.generateId(RemoveMethod.DELAY); System.out.println(id); } } finally { idMaker.stop();
} }
}
|