上面的代码使ZooKeeper服务器触发一个NodeDataChanged事件。 由于DataWatcher为此znode路径设置了监视,因此它会接收数据更改事件的通知。 然后它检索更新的数据,重置监视,并在控制台上打印数据。
使用以下命令编译DataWatcher和DataUpdater类:
$ javac –cp $CLASSPATH DataWatcher.java $ javac –cp $CLASSPATH DataUpdater.java要执行监视器和更新程序,需要打开两个终端窗口。 我要先运行监视器,因为它创建了/MyConfig的znode(如果还未在ZooKeeper的命名空间中创建的话)。 运行监视器之前,请确保ZooKeeper服务器在本地主机上已经运行。
在其中一个终端窗口中,通过运行以下命令来执行watcher类:
$ java –cp $CLASSPATH DataWatcher输出类似于以下屏幕截图所示的消息:
如前面的截图所示,znode路径/MyConfig是由DataWatcher类创建的。 它也打印znode的内容,但没有打印在控制台中,因为我们在创建znode时没有设置任何数据。 当znode被创建时,类中的监视者收到了NodeCreated类型的事件通知,这个通知被打印在控制台中。 DataWatcher类继续运行,并从ZooKeeper服务器侦听/MyConfig节点上的事件。
让我们在另一个终端窗口中运行DataUpdater类:
$ java -cp $CLASSPATH DataUpdater将最初的ZooKeeper特定日志消息记录到控制台后,DataUpdater类运行时没有提示。 它将一个新的UUID字符串设置到ZooKeeper路径/MyConfig的数据字段中。 因此,看到每隔5秒钟,在下面的屏幕截图中显示的输出内容打印在运行DataWatche的终端窗口中:
DataWatcher也可以使用ZooKeeper shell进行测试。 继续像以前一样在终端中运行DataWatcher类,并在另一个终端中调用ZooKeeper shell并运行以下屏幕截图中所示的命令:
在DataWatcher正在运行的终端中,将打印以下消息:
通过互联网提供的流行服务,如电子邮件,文件服务平台,在线游戏等,都是通过跨越多个数据中心的高度可用的成百上千台服务器来服务的,而这些服务器通常在地理位置上分开。 在这种集群中,设置了一些专用的服务器节点来监视生产网络中承载服务或应用程序的服务器的活跃性。 在云计算环境中,也用于管理云环境的这种监控节点被称为云控制器。 这些控制器节点的一个重要工作是实时检测生产服务器的故障,并相应地通知管理员,并采取必要的措施,例如将故障服务器上的应用程序故障转移到另一个服务器,从而确保容错性和高可用性。
在本节中,我们将使用ZooKeeper Java客户端API开发一个简约的分布式集群监视器模型。 使用ZooKeeper的ephemeral znode概念来构建这个监视模型相当简单和优雅,如以下步骤所述:
每个生产服务器运行一个ZooKeeper客户端作为守护进程。 这个过程连接到ZooKeeper服务器,并在/ZooKeeper命名空间的预定义路径(比如/Members)下创建一个带有名称(最好是其网络名称或主机名)的ephemeral znode。
云控制器节点运行ZooKeeper监视器进程,该进程监视路径/Members并监听NodeChildrenChanged类型的事件。 这个监视器进程作为服务或守护进程运行,并设置或重置路径上的监视,并且实现其逻辑以调用适当的模块来为监视事件采取必要的行动。
现在,如果生产服务器由于硬件故障或软件崩溃而关闭,ZooKeeper客户端进程就会被终止,导致服务器和ZooKeeper服务之间的会话被终止。 由于ephemeral znode的属性唯一,每当客户端连接关闭时,ZooKeeper服务会自动删除路径/Members中的znode。
路径中znode的删除引发了NodeChildrenChanged事件,因此云控制器中的观察器进程会收到通知。 通过调用路径/Members中的getChildren方法,可以确定哪个服务器节点已经关闭。
然后,控制器节点可以采取适当的措施,比如执行恢复逻辑以重启另一台服务器中的故障服务。
这个逻辑可以构建为实时工作,保证接近于零停机的时间和高度可用的服务。