ZooKeeper-分布式利器(3)——API与监听使用实例

Zookeeper 作为一个分布式的服务框架,主要用来解决分布式集群中应用系统的一致性问题,它能提供基于类似于文件系统的目录节点树方式的数据存储,但是 Zookeeper 并不是用来专门存储数据的,它的作用主要是用来维护和监控你存储的数据的状态变化。通过监控这些数据状态的变化,从而可以达到基于数据的集群管理。

ZooKeeper官方支持Java和C语言,ZooKeeper社区为其他语言(.NET,python等)提供非官方API。使用ZooKeeper API, 应用程序可以进行连接、CRUD操作、监听事件、设置权限等交互操作。这里以java为例。

简介

ZooKeeper类是ZooKeeper客户端的主类。使用ZooKeeper服务,程序必须实例化一个ZooKeeper对象。所有后续的操作都是调用ZooKeeper的方法。使用最简单的构造方法实例化一个ZooKeeper对象, ZooKeeper(String connectString, int sessionTimeout, Watcher watcher),所需要的参数有,连接url 、会话过期时间、默认初始监听器。

一旦与服务器建立了连接,会话ID就被分配给客户端。客户端将定期向服务器发送心跳,以保持会话有效。只要会话有效期间,客户端可以使用ZooKeeper 中的方法。

由于某些原因,客户端很长一段时间没有发送心跳到服务器,超过了sessionTimeout的值,ZooKeeper服务器会认为会话过期,会话ID将变为无效的ID。同时,客户端ZooKeeper对象将不再可用。为了调用ZooKeeper API方法,应用程序必须创建一个新的客户端ZooKeeper对象。

如果客户端连接到当前ZooKeeper服务器失败或没有响应,那么客户端会在会话ID失效前尝试连接到另一台服务器,如果连接成功,应用程序可以继续使用客户端ZooKeeper对象。

ZooKeeper API的方法既有异步调用也可以同步调用,这是因为java的方法重载,使用同名方法时,传入不同的参数类型或参数个数,就可以切换异步和同步调用。同步方法阻塞线程直到服务器作出响应。异步方法是排队请求并立即结束,执行其他语句。异步方法提供了一个回调对象,该对象在成功请求后执行,或是在返回错误时使用适当的返回码提示错误。

一些成功调用的ZooKeeper API方法可以在ZooKeeper服务器的数据节点上留下监听器。其他成功调用的ZooKeeper API方法可以出发这些监听器。一旦一个监听器被触发,一个事件会被传递到第一个留下监听器的客户端。每个监听器只能被触发一次。因此,每个留下的监听器只能让客户端接收最多一个事件。

一个客户端需要一个Watcher接口的实现类来处理传递给客户端的事件。当一个客户端断开了当前连接并重新连接到ZooKeeper server时,所有已存在的监听器被认为已触发,但事件因未送达客户端而丢失了。为了确保这一点,客户端生成一个特殊的事件告诉事件处理器一个连接已被删除。这个特殊事件的类型是EventNone 状态为sKeeperStateDisconnected。

了解了ZooKeeper客户端的使用以及监听的原理,下面看一个示例。

使用实例——实时更新server列表

场景

在分布式应用中,经常同时启动多个server,调用方(client)选择其中之一发起请求。

分布式应用必须考虑高可用性和可扩展性:Server的应用进程可能会崩溃,或者server所在机器可能会宕机,当server不够应对高并发时,也可能增加server的数量。总而言之,server列表并非一成不变,而是一直处于动态的增减中。这时,调用方就需要实时的更新当前在线的server列表。

思路

根据上篇文章中节点的概念,和本篇的理论部分作为基础,通过ZooKeeper进行功能的实现。具体而言,在启动server时,在ZooKeeper的某个znode(这里用/sgroup)下创建一个子节点,所创建的子节点类型为临时,这样一来,一旦server进程崩溃或宕机,与ZooKeeper连接的session就结束了,那么其所创建的子节点会被ZooKeeper自动删除。当崩溃的server恢复后,或者新增Server时,同样需要在/sgroup节点下创建新的子节点。

对于调用方(client)程序,只需要注册/sgroup子节点的监听,当/sgroup下的子节点增加或减少时,ZooKeeper会通知client,此时client更新server列表。

AppServer实现

AppServer的逻辑很简单,只需要在启动时,在ZooKeeper的“/sgroup”节点下新增一个子节点即可。

AppServer代码

将其打包待用,生成jar时需要指定入口函数。

tips:IDEA打包

IDEA打包1
IDEA打包2

选择入口类

IDEA打包3

检查MANIFEST.MF文件,Main-Class是否正确

检查Main-Class是否正确
build Artifacts

最后可以在out目录中找到zzz.jar文件,作为appServer的运行类文件。

appServer文件

至此,appServer打包完毕。

AppClient实现

AppClient需要监听“/sgroup”下子节点变化事件,当事件发生时,需要得到更新的Server列表。

注册监听“sgroup”下子节点的变化事件,可在getChildren方法中完成。当ZooKeeper会掉监听器的process方法时,判断该事件是否是"/sgroup"下子节点的变化事件,如果是,这调用更新server列表的逻辑,并再次注册对该子节点变化的监听。

AppClient实现

由于暂时不需要拷贝部署来复用,所以直接在IDEA中运行。

运行

首先 运行ZooKeeper。bin/zkServer。 启动一个zkCli来检查是否已存在"sgroup"节点,若不存在,则创建。若存在,则删除并重建此节点。

1.在IDE中运行AppClient,在控制台会得到如下结果。

AppClient

在这里实时显示分布式环境下,所有AppServer的在线情况,此列表会实时更新。

2.开启多个命令行窗口,每个窗口运行AppServer。这里由于我打包名称打成了zzz.jar,所以执行zzz.jar。

java -jar zzz.jar server1 。server1代表server机器的主机名,给每个appserver设定一个不同的主机名,观察AppClient控制台的输出。

添加AppServer

AppClient控制台会输出这样

AppClient输出

依次停掉每个AppServer进程。控制台输出如下

AppServer减少,控制台输出

本篇结束,下篇是关于ArcGIS中的zookeeper 

Too be continue......

本篇参考:http://zookeeper.apache.org/doc/r3.4.5/api/org/apache/zookeeper/ZooKeeper.html,http://coolxing.iteye.com/blog/1871520

你可能感兴趣的:(ZooKeeper-分布式利器(3)——API与监听使用实例)