Zookeeper是分布式环境下一个重要的组件,因为它能在分布式环境下,给我带来很多便利,大大简化了分布式编程的复杂性,本篇散仙将给出一个模拟例子,来演示下如何使用Zookeeper的API编程,来完成分布式环境下配置的同步。大家都知道在一个中大型的规模的集群中,配置文件通常是必不可少的的东西,很多时候,我都需要将在Master上配置好的配置文件,给分发到各个Slave上,以确保整体配置的一致性,在集群规模小的时候我们可能简单的使用远程拷贝或复制即可完成,但是,当集群规模越来越大的时候,我们发现这种方式不仅繁琐,而且容易出错,最要命的是,以后如果改动配置文件的很少一部分的东西,都得需要把所有的配置文件,给重新远程拷贝覆盖一次,那么,怎样才能避免这种牵一发而动全身的事情呢?
事实上,利用Zookeeper,就能够很容易的,高可靠的帮我们完成这件事,我们只需要把配置文件保存在Zookeeper的znode里,然后通过Watch来监听数据变化,进而帮我们实现同步。一个简单的工作图如下所示:
总结流程如下:
序号 实现
1 启动ZK集群
2 客户端在ZK创建一个znode,并写入数据
3 启动各个Server上的Watcher,无限休眠
4 客户端更新znode里数据
5 Watcher的read方法发现数据更新,下拉至本地,更新本地数据
代码如下:
Java代码
1. package com.sanjiesanxian;
2.
3. import java.util.concurrent.CountDownLatch;
4.
5. import org.apache.zookeeper.CreateMode;
6. import org.apache.zookeeper.WatchedEvent;
7. import org.apache.zookeeper.Watcher;
8. import org.apache.zookeeper.ZooKeeper;
9. import org.apache.zookeeper.ZooDefs.Ids;
10. import org.apache.zookeeper.data.Stat;
11.
12.
13. /***
14. * Zookeeper实现分布式配置同步
15. *
16. * @author 秦东亮
17. *
18. * ***/
19. public class SyscConfig implements Watcher{
20.
21. //Zookeeper实例
22. private ZooKeeper zk;
23. private CountDownLatch countDown=new CountDownLatch(1);//同步工具
24. private static final int TIMIOUT=5000;//超时时间
25. private static final String PATH="/sanxian";
26. public SyscConfig(String hosts) {
27.
28. try{
29. zk=new ZooKeeper(hosts, TIMIOUT, new Watcher() {
30.
31. @Override
32. public void process(WatchedEvent event) {
33.
34. if(event.getState().SyncConnected==Event.KeeperState.SyncConnected){
35. //防止在未连接Zookeeper服务器前,执行相关的CURD操作
36. countDown.countDown();//连接初始化,完成,清空计数器
37. }
38.
39. }
40. });
41.
42. }catch(Exception e){
43. e.printStackTrace();
44. }
45. }
46.
47.
48.
49. /***
50. * 写入或更新
51. * 数据
52. * @param path 写入路径
53. * @param value 写入的值
54. * **/
55. public void addOrUpdateData(String path,String data)throws Exception {
56.
57.
58. Stat stat=zk.exists(path, false);
59. if(stat==null){
60. //没有就创建,并写入
61. zk.create(path, data.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
62. System.out.println("新建,并写入数据成功.. ");
63. }else{
64. //存在,就更新
65. zk.setData(path, data.getBytes(), -1);
66. System.out.println("更新成功!");
67. }
68. }
69.
70. /**
71. * 读取数据
72. * @param path 读取的路径
73. * @return 读取数据的内容
74. *
75. * **/
76. public String readData()throws Exception{
77.
78. String s=new String(zk.getData(PATH, this, null));
79.
80. return s;
81. }
82.
83.
84. /**
85. * 关闭zookeeper连接
86. * 释放资源
87. *
88. * **/
89. public void close(){
90.
91. try{
92.
93. zk.close();
94. }catch(Exception e){
95. e.printStackTrace();
96. }
97.
98. }
99.
100.
101. public static void main(String[] args)throws Exception {
102.
103. SyscConfig conf=new SyscConfig("10.2.143.5:2181");
104.
105. conf.addOrUpdateData(PATH, "修真天劫,九死一生。");
106. conf.addOrUpdateData(PATH, "圣人之下,皆为蝼蚁,就算再大的蝼蚁,还是蝼蚁.");
107. conf.addOrUpdateData(PATH, "努力奋斗,实力才是王道! ");
108.
109. //System.out.println("监听器开始监听........");
110. // conf.readData();
111. // Thread.sleep(Long.MAX_VALUE);
112. //conf.readData();
113. conf.close();
114.
115. }
116.
117. @Override
118. public void process(WatchedEvent event){
119. try{
120. if(event.getType()==Event.EventType.NodeDataChanged){
121. System.out.println("变化数据: "+readData());
122. }
123. }catch(Exception e){
124. e.printStackTrace();
125. }
126.
127. }
128. }
模拟客户端输出如下:
Java代码
1.
2. //客户端监听代码
3. SyscConfig conf=new SyscConfig("10.2.143.5:2181");
4.
5. conf.addOrUpdateData(PATH, "修真天劫,九死一生。");
6. conf.addOrUpdateData(PATH, "圣人之下,皆为蝼蚁,就算再大的蝼蚁,还是蝼蚁.");
7. conf.addOrUpdateData(PATH, "努力奋斗,实力才是王道! ");
8.
9. //System.out.println("监听器开始监听........");
10. // conf.readData();
11. // Thread.sleep(Long.MAX_VALUE);
12. //conf.readData();
13. conf.close();
Java代码
1. 更新成功!
2. 更新成功!
3. 更新成功!
模拟服务端输出如下:
Java代码
1. public static void main(String[] args)throws Exception {
2. //服务端监听代码
3. SyscConfig conf=new SyscConfig("10.2.143.36:2181");
4. //conf.addOrUpdateData(PATH, "");
5. System.out.println("模拟服务监听器开始监听........");
6. conf.readData();
7. Thread.sleep(Long.MAX_VALUE);
8. conf.close();
9.
10. }
Java代码
1. 模拟服务监听器开始监听........
2. 数据更新了: 修真天劫,九死一生。
3. 数据更新了: 圣人之下,皆为蝼蚁,就算再大的蝼蚁,还是蝼蚁.
4. 数据更新了: 努力奋斗,实力才是王道!
至此,使用zookeeper来完成配置同步的服务就完成了,我们可以发现,使用zookeeper来编写分布式程序是非常简单可靠的。