转自:http://coolxing.iteye.com/blog/1871520

通过之前的3篇博文, 讲述了ZooKeeper的基础知识点. 可以看出, ZooKeeper提供的核心功能是非常简单, 且易于学习的. 可能会给人留下ZooKeeper并不强大的印象, 事实并非如此, 基于ZooKeeper的核心功能, 我们可以扩展出很多非常有意思的应用. 接下来的几篇博文, 将陆续介绍ZooKeeper的典型应用场景.

场景描述

在分布式应用中, 我们经常同时启动多个server, 调用方(client)选择其中之一发起请求.
分布式应用必须考虑高可用性和可扩展性: server的应用进程可能会崩溃, 或者server本身也可能会宕机. 当server不够时, 也有可能增加server的数量. 总而言之, server列表并非一成不变, 而是一直处于动态的增减中.
那么client如何才能实时的更新server列表呢? 解决的方案很多, 本文将讲述利用ZooKeeper的解决方案.

思路

启动server时, 在zookeeper的某个znode(假设为/sgroup)下创建一个子节点. 所创建的子节点的类型应该为ephemeral, 这样一来, 如果server进程崩溃, 或者server宕机, 与zookeeper连接的session就结束了, 那么其所创建的子节点会被zookeeper自动删除. 当崩溃的server恢复后, 或者新增server时, 同样需要在/sgroup节点下创建新的子节点.
对于client, 只需注册/sgroup子节点的监听, 当/sgroup下的子节点增加或减少时, zookeeper会通知client, 此时client更新server列表.

实现AppServer

AppServer的逻辑非常简单, 只须在启动时, 在zookeeper的"/sgroup"节点下新增一个子节点即可.

Java代码  收藏代码
  1. public class AppServer {
  2. private String groupNode = "sgroup";
  3. private String subNode = "sub";
  4. /**
  5. * 连接zookeeper
  6. * @param address server的地址
  7. */
  8. public void connectZookeeper(String address) throws Exception {
  9. ZooKeeper zk = new ZooKeeper("localhost:4180,localhost:4181,localhost:4182"5000new Watcher() {
  10. public void process(WatchedEvent event) {
  11. // 不做处理
  12. }
  13. });
  14. // 在"/sgroup"下创建子节点
  15. // 子节点的类型设置为EPHEMERAL_SEQUENTIAL, 表明这是一个临时节点, 且在子节点的名称后面加上一串数字后缀
  16. // 将server的地址数据关联到新创建的子节点上
  17. String createdPath = zk.create("/" + groupNode + "/" + subNode, address.getBytes("utf-8"),
  18. Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
  19. System.out.println("create: " + createdPath);
  20. }
  21. /**
  22. * server的工作逻辑写在这个方法中
  23. * 此处不做任何处理, 只让server sleep
  24. */
  25. public void handle() throws InterruptedException {
  26. Thread.sleep(Long.MAX_VALUE);
  27. }
  28. public static void main(String[] args) throws Exception {
  29. // 在参数中指定server的地址
  30. if (args.length == 0) {
  31. System.err.println("The first argument must be server address");
  32. System.exit(1);
  33. }
  34. AppServer as = new AppServer();
  35. as.connectZookeeper(args[0]);
  36. as.handle();
  37. }
  38. }

将其打成appserver.jar后待用, 生成jar时别忘了指定入口函数. 具体的教程请自行搜索.

实现AppClient

AppClient的逻辑比AppServer稍微复杂一些, 需要监听"/sgroup"下子节点的变化事件, 当事件发生时, 需要更新server列表.
注册监听"/sgroup"下子节点的变化事件, 可在getChildren方法中完成. 当zookeeper回调监听器的process方法时, 判断该事件是否是"/sgroup"下子节点的变化事件, 如果是, 则调用更新逻辑, 并再次注册该事件的监听.

Java代码  收藏代码
  1. public class AppClient {
  2. private String groupNode = "sgroup";
  3. private ZooKeeper zk;
  4. private Stat stat = new Stat();
  5. private volatile List<String> serverList;
  6. /**
  7. * 连接zookeeper
  8. */
  9. public void connectZookeeper() throws Exception {
  10. zk = new ZooKeeper("localhost:4180,localhost:4181,localhost:4182"5000new Watcher() {
  11. public void process(WatchedEvent event) {
  12. // 如果发生了"/sgroup"节点下的子节点变化事件, 更新server列表, 并重新注册监听
  13. if (event.getType() == EventType.NodeChildrenChanged
  14. && ("/" + groupNode).equals(event.getPath())) {
  15. try {
  16. updateServerList();
  17. catch (Exception e) {
  18. e.printStackTrace();
  19. }
  20. }
  21. }
  22. });
  23. updateServerList();
  24. }
  25. /**
  26. * 更新server列表
  27. */
  28. private void updateServerList() throws Exception {
  29. List<String> newServerList = new ArrayList<String>();
  30. // 获取并监听groupNode的子节点变化
  31. // watch参数为true, 表示监听子节点变化事件.
  32. // 每次都需要重新注册监听, 因为一次注册, 只能监听一次事件, 如果还想继续保持监听, 必须重新注册
  33. List<String> subList = zk.getChildren("/" + groupNode, true);
  34. for (String subNode : subList) {
  35. // 获取每个子节点下关联的server地址
  36. byte[] data = zk.getData("/" + groupNode + "/" + subNode, false, stat);
  37. newServerList.add(new String(data, "utf-8"));
  38. }
  39. // 替换server列表
  40. serverList = newServerList;
  41. System.out.println("server list updated: " + serverList);
  42. }
  43. /**
  44. * client的工作逻辑写在这个方法中
  45. * 此处不做任何处理, 只让client sleep
  46. */
  47. public void handle() throws InterruptedException {
  48. Thread.sleep(Long.MAX_VALUE);
  49. }
  50. public static void main(String[] args) throws Exception {
  51. AppClient ac = new AppClient();
  52. ac.connectZookeeper();
  53. ac.handle();
  54. }
  55. }

将其打包成appclient.jar后待用, 别忘了指定入口函数.

运行

在运行jar包之前, 需要确认zookeeper中是否已经存在"/sgroup"节点了, 没有不存在, 则创建该节点. 如果存在, 最好先将其删除, 然后再重新创建. ZooKeeper的相关命令可参考我的另一篇博文.
运行appclient.jar: java -jar appclient.jar 开启多个命令行窗口, 每个窗口运行appserver.jar进程:java -jar appserver.jar server0000. "server0000"表示server的地址, 别忘了给每个server设定一个不同的地址. 观察appclient的输出.
依次结束appserver的进程, 观察appclient的输出.
appclient的输出类似于:

Bash代码  收藏代码
  1. server list updated: []
  2. server list updated: [server0000]
  3. server list updated: [server0000, server0001]
  4. server list updated: [server0000, server0001, server0002]
  5. server list updated: [server0000, server0001, server0002, server0003]
  6. server list updated: [server0000, server0001, server0002]
  7. server list updated: [server0000, server0001]
  8. server list updated: [server0000]
  9. server list updated: []

<iframe style="font-size: 12px; line-height: 18px;" src="http://coolxing.iteye.com/iframe_ggbd/794" frameborder="0" scrolling="no" width="468" height="60"></iframe>

ZooKeeper示例 实时更新server列表相关推荐

  1. ZooKeeper学习专题之四:示例 实时更新server列表

    2019独角兽企业重金招聘Python工程师标准>>> [转载请注明作者和原文链接,  如有谬误, 欢迎在评论中指正. ] 通过之前的3篇博文, 讲述了ZooKeeper的基础知识点 ...

  2. ACCESS在程序运行中实时更新查询列表的条件

    最近抽时间在帮其它部门处理数据,使用ACCESS处理数据,里面有个需求,需要在运行时动态的更改一个查询的条件(也就是更新SQL语句内容).之前简单的想法是像更改报表一样的更改查询条件. 报表的格式可以 ...

  3. Exchange server 2003迁移到2010后,手动更新地址列表,提示OAB Versions无效

    Exchange server 2003迁移公共文件夹到2010后,当我们手动更新地址列表时,提示OAB Versions无效,这个不影响邮件收发,但是在客户端会出现OAB不能下载,有时候点击发送和接 ...

  4. php 微信实时更新,微信小程序修改data使页面数据实时更新的代码示例

    本篇文章给大家带来的内容是关于微信小程序修改data使页面数据实时更新的代码示例,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 需求:通过点击button修改dataList中che ...

  5. 【Qt】 Qt中实时更新UI程序示例

    00. 目录 文章目录 00. 目录 01. 概述 02. 开发环境 03. 实时更新UI(非信号与槽) 04. 实时更新UI(信号与槽) 05. 源码下载 06. 附录 01. 概述 Qt在运行时会 ...

  6. ios pusher使用_如何使用JavaScript和Pusher实时更新用户状态

    ios pusher使用 by Rahat Khanna 通过拉哈特·汉娜 如何使用JavaScript和Pusher实时更新用户状态 (How to update a User's Status i ...

  7. Nacos 原理:推+拉打造客户端配置信息的实时更新

    点击蓝色"程序猿DD"关注我哟 来源:逅弈逐码 上篇文章 <Nacos 配置中心原理>我和大家分析了 Nacos 的配置中心原理,主要分析了 Nacos 客户端是如何感 ...

  8. 网易惠惠购物助手:大数据实时更新框架概述

    一.需求是什么? 互联网中的许多应用都有数据实时更新的需求,比如网页搜索如何展示几分钟之前的新闻结果,购物搜索中价格.库存信息的实时更新.在大数据量的情况下,数据如何做到稳定及时的更新?本文以有道购物 ...

  9. 基于 apidoc 生成在线接口文档 (实时更新)(linux系统)

    基于 apidoc 生成在线接口文档 (实时更新)(linux系统) 动态加载,热部署 背景: 规范开发人员的接口文档 文档统一管理,防止本地文档版本不统一 远程部署,保证文档的统一性 主要还是解决, ...

最新文章

  1. 3YAdmin-专注通用权限控制与表单的后台管理系统模板
  2. 删文97篇!前UCLA教授竟是民科?不看好量子通信被禁言
  3. 稀疏数组(数据结构)
  4. HTTP协议方法及状态码(HTTP协议入门必备)
  5. Qt Model/View/Delegate浅谈 - QAbstractListModel
  6. js类(继承)(一)
  7. ASP.NET- 执行SQL超时的解决方案
  8. matlab读取文件xlsfinfo,Matlab读写excel文件函数
  9. 极客ios开发工程师 全套视频教程 教学视频
  10. 计算机作文 六年级,我和电脑600字_六年级作文_小学作文 - 265学校教育网
  11. 蓝桥杯练习——摔手机测试次数
  12. ACL2020-最新录用论文列表分享
  13. 东芝发布全系列消费级硬盘
  14. 谢谢 留下几个 那个有关于C++既QQ群吖
  15. php聊天室的设计实现,基于PHP的Ajax聊天室系统的设计与实现
  16. 关于COM中变体类型VARIANT
  17. 实验一:JSP编程范例
  18. iPhone游戏编程实例:分享成功游戏开发人员的锦囊妙计
  19. TERA: Screen-to-Camera Image Code with Transparency, Efficiency, Robustness and Adaptability论文阅读
  20. Win98 源代码(特别版)

热门文章

  1. java期末考试B卷题及答案,《JAVA程序设计》期末试题B卷
  2. Flutter插件开发--获取Android手机电池信息
  3. 基于Python(Django)+MongoDB实现的(Web)新闻采集和订阅系统【100010319】
  4. mongodb添加多条数据_mongodb一次能插入多少数据
  5. Linux的任督二脉之内存管理线上微信群直播报名(2018.1.29-2.2)
  6. C#专用集合类StringCollection与StringDictionary
  7. Google镜像网站全(4-3更)
  8. 微信小程序开发问题收集及解决方案——样式篇
  9. Android阿面试积累,android项目开发实战密码
  10. 什么是大数据?大数据的特点?