hadoop系列:zookeeper(3)——zookeeper核心原理(事件)

转载 2016年08月29日 23:10:45

1、概述

上一篇文章,我们对zookeeper中的数据组织结构、Leader选举原理进行了讲述(http://blog.csdn.net/yinwenjie/article/details/47613309)。这篇文章我们紧接上文讲解zookeeper中的事件机制。并通过示例代码告诉读者怎么使用zookeeper中的事件通知器:watcher。

2、zookeeper中的监听机制

按照上文中的讲解,我们知道zookeeper主要是为了统一分布式系统中各个节点的工作状态,在资源冲突的情况下协调提供节点资源抢占,提供给每个节点了解整个集群所处状态的途径。这一切的实现都依赖于zookeeper中的事件监听和通知机制

2.1、zookeeper中的事件和状态

事件和状态构成了zookeeper客户端连接描述的两个维度。注意,网上很多帖子都是在介绍zookeeper客户端连接的事件,但是忽略了zookeeper客户端状态的变化也是要进行监听和通知的。这里我们通过下面的两个表详细介绍zookeeper中的事件和状态(zookeeper API中被定义为@Deprecated的事件和状态就不介绍了):

  • zookeeper客户端与zookeeper server连接的状态
连接状态 状态含义
KeeperState.Expired 客户端和服务器在ticktime的时间周期内,是要发送心跳通知的。这是租约协议的一个实现。客户端发送request,告诉服务器其上一个租约时间,服务器收到这个请求后,告诉客户端其下一个租约时间是哪个时间点。当客户端时间戳达到最后一个租约时间,而没有收到服务器发来的任何新租约时间,即认为自己下线(此后客户端会废弃这次连接,并试图重新建立连接)。这个过期状态就是Expired状态
KeeperState.Disconnected 就像上面那个状态所述,当客户端断开一个连接(可能是租约期满,也可能是客户端主动断开)这是客户端和服务器的连接就是Disconnected状态
KeeperState.SyncConnected 一旦客户端和服务器的某一个节点建立连接(注意,虽然集群有多个节点,但是客户端一次连接到一个节点就行了),并完成一次version、zxid的同步,这时的客户端和服务器的连接状态就是SyncConnected
KeeperState.AuthFailed zookeeper客户端进行连接认证失败时,发生该状态

需要说明的是,这些状态在触发时,所记录的事件类型都是:EventType.None

  • zookeeper中的事件。当zookeeper客户端监听某个znode节点”/node-x”时:
zookeeper事件 事件含义
EventType.NodeCreated 当node-x这个节点被创建时,该事件被触发
EventType.NodeChildrenChanged 当node-x这个节点的直接子节点被创建、被删除、子节点数据发生变更时,该事件被触发。
EventType.NodeDataChanged 当node-x这个节点的数据发生变更时,该事件被触发
EventType.NodeDeleted 当node-x这个节点被删除时,该事件被触发。
EventType.None 当zookeeper客户端的连接状态发生变更时,即KeeperState.Expired、KeeperState.Disconnected、KeeperState.SyncConnected、KeeperState.AuthFailed状态切换时,描述的事件类型为EventType.None

2.2、获取相应的响应

我们详细描述了zookeeper客户端连接的状态和zookeeper对znode节点监听的事件类型,下面我们来讲解如何建立zookeeper的watcher监听。在zookeeper中,并没有传统的add****Listener这样的注册监听器的方法。而是采用zk.getChildren(path, watch)、zk.exists(path, watch)、zk.getData(path, watcher, stat)这样的方式为某个znode注册监听。也可以通过zk.register(watcher)注册默认监听。

  • 无论哪一种注册监听的方式,都可以对EventType.None事件进行监听,如果有多个监听器,这些监听器都会收到EventType.None事件。(后文实验)

下表以node-x节点为例,说明调用的注册方法和可监听事件间的关系:

注册方式 NodeCreated NodeChildrenChanged NodeDataChanged EventType.NodeDeleted
zk.getChildren(“/node-x”,watcher)   可监控    
zk.exists(“/node-x”,watcher) 可监控   可监控 可监控
zk.getData(“/node-x”,watcher) 悖论   可监控 可监控

网上很多文章都会引用官方的一个事件表格,这里我就不再引用了,请自行百度吧(反正我觉得80%是抄的,并没有把事件对应的监听关系说清楚),还不如看我这个

2.3、watcher机制

zookeeper中的watcher机制很特别,请注意以下一些关键的经验提醒(这些经验提醒在其他地方找不到):

  • 一个节点可以注册多个watcher,但是分成两种情况,当一个watcher实例多次注册时,zkClient也只会通知一次;当多个不同的watcher实例都注册时,zkClient会依次进行通知(并不是很多网贴粗略说的“多次注册一次通知”),后文将会有实验。

  • 监控同一个节点X的一个watcher实例,通过exist、getData等注册方式多次注册的,zkClient也只会通知一次。这个原理在很多网贴上也都有说明,后文我们同样进行实验。

  • 注意,很多网贴都说zk.getData(“/node-x”,watcher)这种注册方式可以监控节点的NodeCreated事件,实际上是不行的(或者说没有意义)。当一个节点还不存在时,zk.getData这样设置的watcher是会抛出KeeperException$NoNodeException异常的,这次注册会失败,watcher也不会起作用;一旦node-x节点存在了,那这个节点的NodeCreated事件又有什么意义呢?(后文做实验)

  • zookeeper中并没有“永久监听”这种机制。网上所谓实现了”永久监听”的帖子,只是一种编程技巧。思路可以归为两类:一种是“在保证所有节点的watcher都被重新注册”的前提下,再进行目录、子目录的更改;另外一种是“在监听被触发后,被重新注册前,重新取一次节点的信息”确保在“监听真空期”znode没有变化。 有兴趣的读者可自行百度。

下图可以反映zookeeper-watcher的监听真空期:

这里写图片描述

我本人对真空期的处理,更倾向于,注册监听后主动检查本次节点的znode-version和上次节点的znode-version是否一致,来确定是否真空期有节点变化。

3、代码示例

实践是检验真理的唯一途径

3.1、验证监听

3.1.1、验证对一个znode多次注册watcher

为了简单起见,我们先检验一个最好检验的东西,就是为一个znode注册多个watcher时,watcher的通知机制到底是什么样的。这样依赖,第一次接触zookeeper的读者也可以根据代码,快速上手。我们依据前文建立的zookeeper集群,启动了zookeeper的三个工作节点,并注册watcher(我们只会使用其中的一个):

然后我们加测,使用getDate方法是否能够检测一个不存在的节点“Y”的创建事件。

<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">package</span> com.yinwenjie.test.zookeepertest.test;

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> java.io.FileNotFoundException;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> java.io.IOException;

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> org.apache.commons.logging.Log;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> org.apache.commons.logging.LogFactory;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> org.apache.zookeeper.CreateMode;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> org.apache.zookeeper.WatchedEvent;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> org.apache.zookeeper.Watcher;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> org.apache.zookeeper.Watcher.Event.EventType;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> org.apache.zookeeper.Watcher.Event.KeeperState;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> org.apache.zookeeper.ZooDefs.Ids;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> org.apache.zookeeper.ZooKeeper;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> org.springframework.util.Log4jConfigurer;

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> com.yinwenjie.test.zookeepertest.TestZookeeperAgainst;

<span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
 * 这个测试类测试多个watcher监控某一个znode节点的效果。<br>
 * servers:192.168.61.129:2181,192.168.61.130:2181,192.168.61.132:2181<br>
 * 为了验证zk集群的工作效果,我们选择一个节点进行连接(192.168.61.129)。
 *<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @author</span> yinwenjie
 */</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">TestManyWatcher</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">implements</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">Runnable</span> {</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span> {
            Log4jConfigurer.initLogging(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"classpath:log4j.properties"</span>);
        } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span> (FileNotFoundException ex) {
            System.err.println(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Cannot Initialize log4j"</span>);
            System.exit(-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);
        }
    }

    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 日志
     */</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> Log LOGGER = LogFactory.getLog(TestZookeeperAgainst.class);

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">main</span>(String[] args) <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">throws</span> Exception {
        TestManyWatcher testManyWatcher = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> TestManyWatcher();
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Thread(testManyWatcher).start();
    }

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">run</span>() {
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/*
         * 验证过程如下:
         * 1、验证一个节点X上使用exist方式注册的多个监听器(ManyWatcherOne、ManyWatcherTwo),
         *      在节点X发生create事件时的事件通知情况
         * 2、验证一个节点Y上使用getDate方式注册的多个监听器(ManyWatcherOne、ManyWatcherTwo),
         *      在节点X发生create事件时的事件通知情况
         * */</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//默认监听:注册默认监听是为了让None事件都由默认监听处理,</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//不干扰ManyWatcherOne、ManyWatcherTwo的日志输出</span>
        ManyWatcherDefault watcherDefault = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ManyWatcherDefault();
        ZooKeeper zkClient = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>;
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span> {
            zkClient = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ZooKeeper(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"192.168.61.129:2181"</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">120000</span>, watcherDefault);
        } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span> (IOException e) {
            TestManyWatcher.LOGGER.error(e.getMessage(), e);
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span>;
        }
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//默认监听也可以使用register方法注册</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//zkClient.register(watcherDefault);</span>

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//1、========================================================</span>
        TestManyWatcher.LOGGER.info(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"=================以下是第一个实验"</span>);
        String path = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"/X"</span>;
        ManyWatcherOne watcherOneX = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ManyWatcherOne(zkClient , path);
        ManyWatcherTwo watcherTwoX = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ManyWatcherTwo(zkClient , path);
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//注册监听,注意,这里两次exists方法的执行返回都是null,因为“X”节点还不存在</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span> {
            zkClient.exists(path, watcherOneX);
            zkClient.exists(path, watcherTwoX);
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//创建"X"节点,为了简单起见,我们忽略权限问题。</span>
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//并且创建一个临时节点,这样重复跑代码的时候,不用去server上手动删除)</span>
            zkClient.create(path, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">""</span>.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
        } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span> (Exception e) {
            TestManyWatcher.LOGGER.error(e.getMessage(), e);
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span>;
        }
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//TODO 注意观察日志,根据原理我们猜测理想情况下ManyWatcherTwo和ManyWatcherOne都会被通知。</span>

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//2、========================================================</span>
        TestManyWatcher.LOGGER.info(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"=================以下是第二个实验"</span>);
        path = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"/Y"</span>;
        ManyWatcherOne watcherOneY = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ManyWatcherOne(zkClient , path);
        ManyWatcherTwo watcherTwoY = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ManyWatcherTwo(zkClient , path);
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//注册监听,注意,这里使用两次getData方法注册监听,"Y"节点目前并不存在</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span> {
            zkClient.getData(path, watcherOneY, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>);
            zkClient.getData(path, watcherTwoY, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>);
        } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span> (Exception e) {
            TestManyWatcher.LOGGER.error(e.getMessage(), e);
        }
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//TODO 注意观察日志,因为"Y"节点不存在,所以getData就会出现异常。watcherOneY、watcherTwoY的注册都不起任何作用。</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//然后我们在报了异常的情况下,创建"Y"节点,根据原理,不会有任何watcher响应"Y"节点的create事件</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span> {
            zkClient.create(path, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">""</span>.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
        } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span> (Exception e) {
            TestManyWatcher.LOGGER.error(e.getMessage(), e);
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span>;
        }

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//下面这段代码可以忽略,是为了观察zk的原理。让守护线程保持不退出</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">synchronized</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>) {
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span> {
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.wait();
            } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span> (InterruptedException e) {
                TestManyWatcher.LOGGER.error(e.getMessage(), e);
                System.exit(-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);
            }
        }
    }
}

<span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
 * 这是默认的watcher实现。
 *<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @author</span> yinwenjie
 */</span>
class ManyWatcherDefault implements Watcher {
    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 日志
     */</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> Log LOGGER = LogFactory.getLog(ManyWatcherDefault.class);

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">process</span>(WatchedEvent event) {
        KeeperState keeperState = event.getState();
        EventType eventType = event.getType();
        ManyWatcherDefault.LOGGER.info(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"=========默认监听到None事件:keeperState = "</span> 
                + keeperState + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"  :  eventType = "</span> + eventType);
    }
}

<span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
 * 这是第一种watcher
 *<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @author</span> yinwenjie
 */</span>
class ManyWatcherOne implements Watcher {
    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 日志
     */</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> Log LOGGER = LogFactory.getLog(ManyWatcherOne.class);

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> ZooKeeper zkClient;

    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 被监控的znode地址
     */</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> String watcherPath;

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">ManyWatcherOne</span>(ZooKeeper zkClient , String watcherPath) {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.zkClient = zkClient;
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.watcherPath = watcherPath;
    }

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">process</span>(WatchedEvent event) {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span> {
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.zkClient.exists(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.watcherPath, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>);
        } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span> (Exception e) {
            ManyWatcherOne.LOGGER.error(e.getMessage(), e);
        }
        KeeperState keeperState = event.getState();
        EventType eventType = event.getType();
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//这个属性是发生事件的path</span>
        String eventPath = event.getPath();

        ManyWatcherOne.LOGGER.info(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"=========ManyWatcherOne监听到"</span> + eventPath + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"地址发生事件:"</span>
                + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"keeperState = "</span> + keeperState + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"  :  eventType = "</span> + eventType);
    }
}

<span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
 * 这是第二种watcher
 *<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @author</span> yinwenjie
 */</span>
class ManyWatcherTwo implements Watcher {
    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 日志
     */</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> Log LOGGER = LogFactory.getLog(ManyWatcherOne.class);

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> ZooKeeper zkClient;

    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 被监控的znode地址
     */</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> String watcherPath;

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">ManyWatcherTwo</span>(ZooKeeper zkClient, String watcherPath) {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.zkClient = zkClient;
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.watcherPath = watcherPath;
    }

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">process</span>(WatchedEvent event) {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span> {
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.zkClient.exists(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.watcherPath, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>);
        } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span> (Exception e) {
            ManyWatcherTwo.LOGGER.error(e.getMessage(), e);
        }
        KeeperState keeperState = event.getState();
        EventType eventType = event.getType();
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//这个属性是发生事件的path</span>
        String eventPath = event.getPath();

        ManyWatcherTwo.LOGGER.info(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"=========ManyWatcherTwo监听到"</span> + eventPath + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"地址发生事件:"</span>
                + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"keeperState = "</span> + keeperState + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"  :  eventType = "</span> + eventType);
    }
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li><li style="box-sizing: border-box; padding: 0px 5px;">72</li><li style="box-sizing: border-box; padding: 0px 5px;">73</li><li style="box-sizing: border-box; padding: 0px 5px;">74</li><li style="box-sizing: border-box; padding: 0px 5px;">75</li><li style="box-sizing: border-box; padding: 0px 5px;">76</li><li style="box-sizing: border-box; padding: 0px 5px;">77</li><li style="box-sizing: border-box; padding: 0px 5px;">78</li><li style="box-sizing: border-box; padding: 0px 5px;">79</li><li style="box-sizing: border-box; padding: 0px 5px;">80</li><li style="box-sizing: border-box; padding: 0px 5px;">81</li><li style="box-sizing: border-box; padding: 0px 5px;">82</li><li style="box-sizing: border-box; padding: 0px 5px;">83</li><li style="box-sizing: border-box; padding: 0px 5px;">84</li><li style="box-sizing: border-box; padding: 0px 5px;">85</li><li style="box-sizing: border-box; padding: 0px 5px;">86</li><li style="box-sizing: border-box; padding: 0px 5px;">87</li><li style="box-sizing: border-box; padding: 0px 5px;">88</li><li style="box-sizing: border-box; padding: 0px 5px;">89</li><li style="box-sizing: border-box; padding: 0px 5px;">90</li><li style="box-sizing: border-box; padding: 0px 5px;">91</li><li style="box-sizing: border-box; padding: 0px 5px;">92</li><li style="box-sizing: border-box; padding: 0px 5px;">93</li><li style="box-sizing: border-box; padding: 0px 5px;">94</li><li style="box-sizing: border-box; padding: 0px 5px;">95</li><li style="box-sizing: border-box; padding: 0px 5px;">96</li><li style="box-sizing: border-box; padding: 0px 5px;">97</li><li style="box-sizing: border-box; padding: 0px 5px;">98</li><li style="box-sizing: border-box; padding: 0px 5px;">99</li><li style="box-sizing: border-box; padding: 0px 5px;">100</li><li style="box-sizing: border-box; padding: 0px 5px;">101</li><li style="box-sizing: border-box; padding: 0px 5px;">102</li><li style="box-sizing: border-box; padding: 0px 5px;">103</li><li style="box-sizing: border-box; padding: 0px 5px;">104</li><li style="box-sizing: border-box; padding: 0px 5px;">105</li><li style="box-sizing: border-box; padding: 0px 5px;">106</li><li style="box-sizing: border-box; padding: 0px 5px;">107</li><li style="box-sizing: border-box; padding: 0px 5px;">108</li><li style="box-sizing: border-box; padding: 0px 5px;">109</li><li style="box-sizing: border-box; padding: 0px 5px;">110</li><li style="box-sizing: border-box; padding: 0px 5px;">111</li><li style="box-sizing: border-box; padding: 0px 5px;">112</li><li style="box-sizing: border-box; padding: 0px 5px;">113</li><li style="box-sizing: border-box; padding: 0px 5px;">114</li><li style="box-sizing: border-box; padding: 0px 5px;">115</li><li style="box-sizing: border-box; padding: 0px 5px;">116</li><li style="box-sizing: border-box; padding: 0px 5px;">117</li><li style="box-sizing: border-box; padding: 0px 5px;">118</li><li style="box-sizing: border-box; padding: 0px 5px;">119</li><li style="box-sizing: border-box; padding: 0px 5px;">120</li><li style="box-sizing: border-box; padding: 0px 5px;">121</li><li style="box-sizing: border-box; padding: 0px 5px;">122</li><li style="box-sizing: border-box; padding: 0px 5px;">123</li><li style="box-sizing: border-box; padding: 0px 5px;">124</li><li style="box-sizing: border-box; padding: 0px 5px;">125</li><li style="box-sizing: border-box; padding: 0px 5px;">126</li><li style="box-sizing: border-box; padding: 0px 5px;">127</li><li style="box-sizing: border-box; padding: 0px 5px;">128</li><li style="box-sizing: border-box; padding: 0px 5px;">129</li><li style="box-sizing: border-box; padding: 0px 5px;">130</li><li style="box-sizing: border-box; padding: 0px 5px;">131</li><li style="box-sizing: border-box; padding: 0px 5px;">132</li><li style="box-sizing: border-box; padding: 0px 5px;">133</li><li style="box-sizing: border-box; padding: 0px 5px;">134</li><li style="box-sizing: border-box; padding: 0px 5px;">135</li><li style="box-sizing: border-box; padding: 0px 5px;">136</li><li style="box-sizing: border-box; padding: 0px 5px;">137</li><li style="box-sizing: border-box; padding: 0px 5px;">138</li><li style="box-sizing: border-box; padding: 0px 5px;">139</li><li style="box-sizing: border-box; padding: 0px 5px;">140</li><li style="box-sizing: border-box; padding: 0px 5px;">141</li><li style="box-sizing: border-box; padding: 0px 5px;">142</li><li style="box-sizing: border-box; padding: 0px 5px;">143</li><li style="box-sizing: border-box; padding: 0px 5px;">144</li><li style="box-sizing: border-box; padding: 0px 5px;">145</li><li style="box-sizing: border-box; padding: 0px 5px;">146</li><li style="box-sizing: border-box; padding: 0px 5px;">147</li><li style="box-sizing: border-box; padding: 0px 5px;">148</li><li style="box-sizing: border-box; padding: 0px 5px;">149</li><li style="box-sizing: border-box; padding: 0px 5px;">150</li><li style="box-sizing: border-box; padding: 0px 5px;">151</li><li style="box-sizing: border-box; padding: 0px 5px;">152</li><li style="box-sizing: border-box; padding: 0px 5px;">153</li><li style="box-sizing: border-box; padding: 0px 5px;">154</li><li style="box-sizing: border-box; padding: 0px 5px;">155</li><li style="box-sizing: border-box; padding: 0px 5px;">156</li><li style="box-sizing: border-box; padding: 0px 5px;">157</li><li style="box-sizing: border-box; padding: 0px 5px;">158</li><li style="box-sizing: border-box; padding: 0px 5px;">159</li><li style="box-sizing: border-box; padding: 0px 5px;">160</li><li style="box-sizing: border-box; padding: 0px 5px;">161</li><li style="box-sizing: border-box; padding: 0px 5px;">162</li><li style="box-sizing: border-box; padding: 0px 5px;">163</li><li style="box-sizing: border-box; padding: 0px 5px;">164</li><li style="box-sizing: border-box; padding: 0px 5px;">165</li><li style="box-sizing: border-box; padding: 0px 5px;">166</li><li style="box-sizing: border-box; padding: 0px 5px;">167</li><li style="box-sizing: border-box; padding: 0px 5px;">168</li><li style="box-sizing: border-box; padding: 0px 5px;">169</li><li style="box-sizing: border-box; padding: 0px 5px;">170</li><li style="box-sizing: border-box; padding: 0px 5px;">171</li><li style="box-sizing: border-box; padding: 0px 5px;">172</li><li style="box-sizing: border-box; padding: 0px 5px;">173</li><li style="box-sizing: border-box; padding: 0px 5px;">174</li><li style="box-sizing: border-box; padding: 0px 5px;">175</li><li style="box-sizing: border-box; padding: 0px 5px;">176</li><li style="box-sizing: border-box; padding: 0px 5px;">177</li><li style="box-sizing: border-box; padding: 0px 5px;">178</li><li style="box-sizing: border-box; padding: 0px 5px;">179</li><li style="box-sizing: border-box; padding: 0px 5px;">180</li><li style="box-sizing: border-box; padding: 0px 5px;">181</li><li style="box-sizing: border-box; padding: 0px 5px;">182</li><li style="box-sizing: border-box; padding: 0px 5px;">183</li><li style="box-sizing: border-box; padding: 0px 5px;">184</li><li style="box-sizing: border-box; padding: 0px 5px;">185</li><li style="box-sizing: border-box; padding: 0px 5px;">186</li><li style="box-sizing: border-box; padding: 0px 5px;">187</li><li style="box-sizing: border-box; padding: 0px 5px;">188</li><li style="box-sizing: border-box; padding: 0px 5px;">189</li><li style="box-sizing: border-box; padding: 0px 5px;">190</li><li style="box-sizing: border-box; padding: 0px 5px;">191</li><li style="box-sizing: border-box; padding: 0px 5px;">192</li><li style="box-sizing: border-box; padding: 0px 5px;">193</li><li style="box-sizing: border-box; padding: 0px 5px;">194</li><li style="box-sizing: border-box; padding: 0px 5px;">195</li><li style="box-sizing: border-box; padding: 0px 5px;">196</li><li style="box-sizing: border-box; padding: 0px 5px;">197</li><li style="box-sizing: border-box; padding: 0px 5px;">198</li><li style="box-sizing: border-box; padding: 0px 5px;">199</li><li style="box-sizing: border-box; padding: 0px 5px;">200</li><li style="box-sizing: border-box; padding: 0px 5px;">201</li><li style="box-sizing: border-box; padding: 0px 5px;">202</li><li style="box-sizing: border-box; padding: 0px 5px;">203</li><li style="box-sizing: border-box; padding: 0px 5px;">204</li><li style="box-sizing: border-box; padding: 0px 5px;">205</li><li style="box-sizing: border-box; padding: 0px 5px;">206</li><li style="box-sizing: border-box; padding: 0px 5px;">207</li><li style="box-sizing: border-box; padding: 0px 5px;">208</li><li style="box-sizing: border-box; padding: 0px 5px;">209</li></ul>

代码中的注释自我感觉写得比较详细,这里就不再介绍了。以下是执行这段测试代码后,所运行的Log4j的日志信息。

<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;">[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2015</span>-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">08</span>-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">18</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">19</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">27</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">37</span>] INFO  Thread-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span> Initiating client connection, connectString=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">192.168</span><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">.61</span><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">.129</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2181</span> sessionTimeout=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">120000</span> watcher=<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">com</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.yinwenjie</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.test</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.zookeepertest</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.test</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.ManyWatcherDefault</span><span class="hljs-localvars" style="box-sizing: border-box;">@6</span>db38815 (ZooKeeper<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.java</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">379</span>)
  [<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2015</span>-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">08</span>-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">18</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">19</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">27</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">37</span>] INFO  Thread-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span> =================以下是第一个实验 (TestManyWatcher<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.java</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">67</span>)
  [<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2015</span>-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">08</span>-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">18</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">19</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">27</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">37</span>] INFO  Thread-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>-SendThread() Opening socket connection to server /<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">192.168</span><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">.61</span><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">.129</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2181</span> (ClientCnxn<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.java</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1061</span>)
  [<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2015</span>-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">08</span>-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">18</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">19</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">27</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">37</span>] INFO  Thread-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>-SendThread(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">192.168</span><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">.61</span><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">.129</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2181</span>) Socket connection established to <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">192.168</span><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">.61</span><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">.129</span>/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">192.168</span><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">.61</span><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">.129</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2181</span>, initiating session (ClientCnxn<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.java</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">950</span>)
  [<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2015</span>-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">08</span>-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">18</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">19</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">27</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">37</span>] INFO  Thread-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>-SendThread(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">192.168</span><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">.61</span><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">.129</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2181</span>) Session establishment complete on server <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">192.168</span><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">.61</span><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">.129</span>/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">192.168</span><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">.61</span><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">.129</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2181</span>, sessionid = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0x14f40902e2a0000</span>, negotiated timeout = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">40000</span> (ClientCnxn<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.java</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">739</span>)
  [<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2015</span>-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">08</span>-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">18</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">19</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">27</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">37</span>] INFO  Thread-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>-EventThread =========默认监听到None事件:keeperState = SyncConnected  :  eventType = None (TestManyWatcher<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.java</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">130</span>)
  [<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2015</span>-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">08</span>-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">18</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">19</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">27</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">37</span>] INFO  Thread-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span> =================以下是第二个实验 (TestManyWatcher<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.java</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">85</span>)
  [<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2015</span>-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">08</span>-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">18</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">19</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">27</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">37</span>] INFO  Thread-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>-EventThread =========ManyWatcherTwo监听到/<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">X</span>地址发生事件:keeperState = SyncConnected  :  eventType = NodeCreated (TestManyWatcher<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.java</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">206</span>)
  [<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2015</span>-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">08</span>-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">18</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">19</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">27</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">37</span>] INFO  Thread-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>-EventThread =========ManyWatcherOne监听到/<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">X</span>地址发生事件:keeperState = SyncConnected  :  eventType = NodeCreated (TestManyWatcher<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.java</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">168</span>)
  [<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2015</span>-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">08</span>-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">18</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">19</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">27</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">37</span>] ERROR Thread-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span> KeeperErrorCode = NoNode for /<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">Y</span> (TestManyWatcher<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.java</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">94</span>)
  org<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.apache</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.zookeeper</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.KeeperException</span>$NoNodeException: KeeperErrorCode = NoNode for /<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">Y</span>
    at org<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.apache</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.zookeeper</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.KeeperException</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.create</span>(KeeperException<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.java</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">102</span>)
    at org<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.apache</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.zookeeper</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.KeeperException</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.create</span>(KeeperException<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.java</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">42</span>)
    at org<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.apache</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.zookeeper</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.ZooKeeper</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getData</span>(ZooKeeper<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.java</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">927</span>)
    at <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">com</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.yinwenjie</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.test</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.zookeepertest</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.test</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.TestManyWatcher</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.run</span>(TestManyWatcher<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.java</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">91</span>)
    at java<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.lang</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.Thread</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.run</span>(Unknown Source)</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li></ul>

在我们调用getData,抛出异常后,我们试图创建“Y”节点。并且发现没有任何监听日志输出。于是我们肯定了上文中的两个描述:

  • 针对一个节点发生的事件,zkClient是不是做多次watcher通知,和使用什么方法注册的没有关系,关键在于所注册的watcher实例是否为同一个实例。

  • 使用getDate注册一个不存在的节点的监听,并试图监听这个节点create event是无法实现的。因为会抛出NoNodeException异常,注册watcher的动作也会变得无效。

3.1.2、验证default watcher监听EventType.None事件

这个测试在指定了默认watcher监听和没有指定默认watcher监听的两种情况下。zkClient对Event-NONE事件的响应机制。

<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">package</span> com.yinwenjie.test.zookeepertest.test;

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> java.io.FileNotFoundException;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> java.io.IOException;

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> org.apache.commons.logging.Log;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> org.apache.commons.logging.LogFactory;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> org.apache.zookeeper.CreateMode;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> org.apache.zookeeper.WatchedEvent;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> org.apache.zookeeper.Watcher;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> org.apache.zookeeper.ZooKeeper;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> org.apache.zookeeper.Watcher.Event.EventType;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> org.apache.zookeeper.Watcher.Event.KeeperState;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> org.apache.zookeeper.ZooDefs.Ids;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> org.springframework.util.Log4jConfigurer;

<span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
 * 这个测试类测试在指定了默认watcher,并且有不止一个watcher实例的情况下。zkClient对Event-NONE事件的响应机制。
 * servers:192.168.61.129:2181,192.168.61.130:2181,192.168.61.132:2181<br>
 * 我们选择一个节点进行连接(192.168.61.129),这样好在主动停止这个zk节点后,观察watcher的响应情况。
 *<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @author</span> yinwenjie
 */</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">TestEventNoneWatcher</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">implements</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">Runnable</span> {</span>

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span> {
            Log4jConfigurer.initLogging(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"classpath:log4j.properties"</span>);
        } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span> (FileNotFoundException ex) {
            System.err.println(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Cannot Initialize log4j"</span>);
            System.exit(-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);
        }
    }

    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 日志
     */</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> Log LOGGER = LogFactory.getLog(TestEventNoneWatcher.class);

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> ZooKeeper zkClient = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>;

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">main</span>(String[] args) <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">throws</span> Exception {
        TestEventNoneWatcher testEventNoneWatcher = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> TestEventNoneWatcher();
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Thread(testEventNoneWatcher).start();
    }

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">run</span>() {
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/*
         * 验证过程如下:
         * 1、连接zk后,并不进行进行默认的watcher的注册,并且使用exist方法注册一个监听节点"X"的监听器。
         *      (完成后主线程进入等待状态)
         * 2、关闭192.168.61.129:2181这个zk节点,让Disconnected事件发生。
         *      观察到底是哪个watcher响应这些None事件。
         * */</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//1、========================================================</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//注册默认监听</span>
        EventNodeWatcherDefault watcherDefault = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> EventNodeWatcherDefault(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>);
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span> {
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.zkClient = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ZooKeeper(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"192.168.61.129:2181"</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">120000</span>, watcherDefault);
        } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span> (IOException e) {
            TestEventNoneWatcher.LOGGER.error(e.getMessage(), e);
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span>;
        }

        String path = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"/X"</span>;
        EventNodeWatcherOne eventNodeWatcherOne = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> EventNodeWatcherOne(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.zkClient , path);
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//注册监听,注意,这里两次exists方法的执行返回都是null,因为“X”节点还不存在</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span> {
            zkClient.exists(path, eventNodeWatcherOne);
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//创建"X"节点,为了简单起见,我们忽略权限问题。</span>
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//并且创建一个临时节点,这样重复跑代码的时候,不用去server上手动删除)</span>
            zkClient.create(path, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">""</span>.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
        } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span> (Exception e) {
            TestEventNoneWatcher.LOGGER.error(e.getMessage(), e);
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span>;
        }

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//完成注册后,主线程等待。然后关闭192.168.61.129上的zk节点</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">synchronized</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>) {
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span> {
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.wait();
            } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span> (InterruptedException e) {
                TestEventNoneWatcher.LOGGER.error(e.getMessage(), e);
                System.exit(-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);
            }
        }
    }

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> ZooKeeper <span class="hljs-title" style="box-sizing: border-box;">getZkClient</span>() {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> zkClient;
    }
}

<span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
 * 这是默认的watcher实现。
 *<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @author</span> yinwenjie
 */</span>
class EventNodeWatcherDefault implements Watcher {
    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 日志
     */</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> Log LOGGER = LogFactory.getLog(EventNodeWatcherDefault.class);

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> TestEventNoneWatcher eventNoneWatcherThead;

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">EventNodeWatcherDefault</span>(TestEventNoneWatcher eventNoneWatcherThead) {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.eventNoneWatcherThead = eventNoneWatcherThead;
    }

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">process</span>(WatchedEvent event) {
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//重新注册监听</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.eventNoneWatcherThead.getZkClient().register(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>);

        KeeperState keeperState = event.getState();
        EventType eventType = event.getType();
        EventNodeWatcherDefault.LOGGER.info(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"=========默认EventNodeWatcher监听到None事件:keeperState = "</span> 
                + keeperState + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"  :  eventType = "</span> + eventType);
    }
}

<span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
 * 这是第一种watcher
 *<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @author</span> yinwenjie
 */</span>
class EventNodeWatcherOne implements Watcher {
    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 日志
     */</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> Log LOGGER = LogFactory.getLog(EventNodeWatcherOne.class);

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> ZooKeeper zkClient;

    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 被监控的znode地址
     */</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> String watcherPath;

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">EventNodeWatcherOne</span>(ZooKeeper zkClient , String watcherPath) {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.zkClient = zkClient;
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.watcherPath = watcherPath;
    }

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">process</span>(WatchedEvent event) {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span> {
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.zkClient.exists(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.watcherPath, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>);
        } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span> (Exception e) {
            EventNodeWatcherOne.LOGGER.error(e.getMessage(), e);
        }
        KeeperState keeperState = event.getState();
        EventType eventType = event.getType();

        EventNodeWatcherOne.LOGGER.info(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"=========EventNodeWatcherOne监听到事件:keeperState = "</span> 
                + keeperState + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"  :  eventType = "</span> + eventType);
    }
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li><li style="box-sizing: border-box; padding: 0px 5px;">72</li><li style="box-sizing: border-box; padding: 0px 5px;">73</li><li style="box-sizing: border-box; padding: 0px 5px;">74</li><li style="box-sizing: border-box; padding: 0px 5px;">75</li><li style="box-sizing: border-box; padding: 0px 5px;">76</li><li style="box-sizing: border-box; padding: 0px 5px;">77</li><li style="box-sizing: border-box; padding: 0px 5px;">78</li><li style="box-sizing: border-box; padding: 0px 5px;">79</li><li style="box-sizing: border-box; padding: 0px 5px;">80</li><li style="box-sizing: border-box; padding: 0px 5px;">81</li><li style="box-sizing: border-box; padding: 0px 5px;">82</li><li style="box-sizing: border-box; padding: 0px 5px;">83</li><li style="box-sizing: border-box; padding: 0px 5px;">84</li><li style="box-sizing: border-box; padding: 0px 5px;">85</li><li style="box-sizing: border-box; padding: 0px 5px;">86</li><li style="box-sizing: border-box; padding: 0px 5px;">87</li><li style="box-sizing: border-box; padding: 0px 5px;">88</li><li style="box-sizing: border-box; padding: 0px 5px;">89</li><li style="box-sizing: border-box; padding: 0px 5px;">90</li><li style="box-sizing: border-box; padding: 0px 5px;">91</li><li style="box-sizing: border-box; padding: 0px 5px;">92</li><li style="box-sizing: border-box; padding: 0px 5px;">93</li><li style="box-sizing: border-box; padding: 0px 5px;">94</li><li style="box-sizing: border-box; padding: 0px 5px;">95</li><li style="box-sizing: border-box; padding: 0px 5px;">96</li><li style="box-sizing: border-box; padding: 0px 5px;">97</li><li style="box-sizing: border-box; padding: 0px 5px;">98</li><li style="box-sizing: border-box; padding: 0px 5px;">99</li><li style="box-sizing: border-box; padding: 0px 5px;">100</li><li style="box-sizing: border-box; padding: 0px 5px;">101</li><li style="box-sizing: border-box; padding: 0px 5px;">102</li><li style="box-sizing: border-box; padding: 0px 5px;">103</li><li style="box-sizing: border-box; padding: 0px 5px;">104</li><li style="box-sizing: border-box; padding: 0px 5px;">105</li><li style="box-sizing: border-box; padding: 0px 5px;">106</li><li style="box-sizing: border-box; padding: 0px 5px;">107</li><li style="box-sizing: border-box; padding: 0px 5px;">108</li><li style="box-sizing: border-box; padding: 0px 5px;">109</li><li style="box-sizing: border-box; padding: 0px 5px;">110</li><li style="box-sizing: border-box; padding: 0px 5px;">111</li><li style="box-sizing: border-box; padding: 0px 5px;">112</li><li style="box-sizing: border-box; padding: 0px 5px;">113</li><li style="box-sizing: border-box; padding: 0px 5px;">114</li><li style="box-sizing: border-box; padding: 0px 5px;">115</li><li style="box-sizing: border-box; padding: 0px 5px;">116</li><li style="box-sizing: border-box; padding: 0px 5px;">117</li><li style="box-sizing: border-box; padding: 0px 5px;">118</li><li style="box-sizing: border-box; padding: 0px 5px;">119</li><li style="box-sizing: border-box; padding: 0px 5px;">120</li><li style="box-sizing: border-box; padding: 0px 5px;">121</li><li style="box-sizing: border-box; padding: 0px 5px;">122</li><li style="box-sizing: border-box; padding: 0px 5px;">123</li><li style="box-sizing: border-box; padding: 0px 5px;">124</li><li style="box-sizing: border-box; padding: 0px 5px;">125</li><li style="box-sizing: border-box; padding: 0px 5px;">126</li><li style="box-sizing: border-box; padding: 0px 5px;">127</li><li style="box-sizing: border-box; padding: 0px 5px;">128</li><li style="box-sizing: border-box; padding: 0px 5px;">129</li><li style="box-sizing: border-box; padding: 0px 5px;">130</li><li style="box-sizing: border-box; padding: 0px 5px;">131</li><li style="box-sizing: border-box; padding: 0px 5px;">132</li><li style="box-sizing: border-box; padding: 0px 5px;">133</li><li style="box-sizing: border-box; padding: 0px 5px;">134</li><li style="box-sizing: border-box; padding: 0px 5px;">135</li><li style="box-sizing: border-box; padding: 0px 5px;">136</li><li style="box-sizing: border-box; padding: 0px 5px;">137</li><li style="box-sizing: border-box; padding: 0px 5px;">138</li><li style="box-sizing: border-box; padding: 0px 5px;">139</li><li style="box-sizing: border-box; padding: 0px 5px;">140</li><li style="box-sizing: border-box; padding: 0px 5px;">141</li><li style="box-sizing: border-box; padding: 0px 5px;">142</li><li style="box-sizing: border-box; padding: 0px 5px;">143</li><li style="box-sizing: border-box; padding: 0px 5px;">144</li><li style="box-sizing: border-box; padding: 0px 5px;">145</li><li style="box-sizing: border-box; padding: 0px 5px;">146</li><li style="box-sizing: border-box; padding: 0px 5px;">147</li><li style="box-sizing: border-box; padding: 0px 5px;">148</li><li style="box-sizing: border-box; padding: 0px 5px;">149</li><li style="box-sizing: border-box; padding: 0px 5px;">150</li><li style="box-sizing: border-box; padding: 0px 5px;">151</li><li style="box-sizing: border-box; padding: 0px 5px;">152</li><li style="box-sizing: border-box; padding: 0px 5px;">153</li><li style="box-sizing: border-box; padding: 0px 5px;">154</li></ul>

我们来执行这段代码。打印的Log4j的信息如下:

这里写图片描述

从log4j的日志可以看到,默认的watcher,监听到了zkClient的Event-None事件。而节点”X”的创建事件由EventNodeWatcherOne的实例进行了监听。接下来测试代码进入了等待状态。

然后我们关闭这个zkServer节点,并且观察watcher的响应情况:

<code class="hljs r has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;">[root@vm1 ~]<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># zkServer.sh stop</span>
JMX enabled by default
Using config: /usr/zookeeper-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3.4</span><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">.6</span>/bin/../conf/zoo.cfg
Stopping zookeeper <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span> STOPPED</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>

以下是zk客户端响应的log4j日志信息:

这里写图片描述

红圈处,我们看到zkServer的节点断开后,EventType.None事件被已经注册的两个watcher分别响应了一次。这里注意两个异常:第一个异常是断开连接后,socket报的错误,从错误中我们可以看到zookeeper客户端的连接使用了sun的nio框架(如果您不知道nio请自行百度,或者关注我后续的博文);第二个错,是在断开连接后,EventNodeWatcherOne试图重新使用exists方式注册监听,所以报错。

可见EventType.None事件,会由所有的监听器全部响应。所以这里我们的编程建议是:一定要使用默认监听器,并由默认监听器来响应EventType.None事件;其他针对znode节点的接听器,只针对节点事件进行处理,使用if语句进行过滤,如果发现是EventType.None事件,则忽略不作处理。

当然,任何编码过程都是要根据您自己的业务规则来设计。以上的建议只是笔者针对一般业务情况的处理方式。

3.2、协调独享资源的抢占

下面的代码,用来向各位看官演示,zookeeper利用其znode机制,是怎么完成资源抢占的协调过程的。为了简化代码片段,我没有使用默认的watcher监听,所以启动的时候会报一个空指针错误是正常的,原因在org.apache.zookeeper.ClientCnxn的524行(3.4.5版本):

<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">processEvent</span>(Object <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">event</span>) {
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span> {
     <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">event</span> instanceof WatcherSetEventPair) {
         <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// each watcher will process the event</span>
         WatcherSetEventPair pair = (WatcherSetEventPair) <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">event</span>;
         <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> (Watcher watcher : pair.watchers) {
             <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span> {
                 watcher.process(pair.<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">event</span>);
             } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span> (Throwable t) {
                 LOG.error(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Error while calling watcher "</span>, t);
             }
         }
     } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> {
         。。。。</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li></ul>

通过这段代码,读者还可以跟踪出各种事件的响应方式。但这个不是本文中扩散讨论的了,在我后续hadoop系列文章中,我还会介绍zookeeper,那时我们会深入讨论zookeeper客户端重连过程、更深层次的watcher事件机制。

话锋转回,下面的代码是如何使用zookeeper进行独享资源的协调,同样的,代码中注释写得比较清楚,就不在进行文字叙述了(代码是可以运行的,但是不建议拷贝粘贴哈^_^):

<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">package</span> com.yinwenjie.test.zookeepertest;

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> java.io.FileNotFoundException;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> java.util.List;

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> org.apache.commons.lang.StringUtils;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> org.apache.commons.logging.Log;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> org.apache.commons.logging.LogFactory;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> org.apache.zookeeper.CreateMode;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> org.apache.zookeeper.WatchedEvent;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> org.apache.zookeeper.Watcher;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> org.apache.zookeeper.Watcher.Event.EventType;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> org.apache.zookeeper.ZooDefs.Ids;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> org.apache.zookeeper.ZooKeeper;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> org.apache.zookeeper.data.Stat;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> org.springframework.util.Log4jConfigurer;

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">TestZookeeperAgainst</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">implements</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">Runnable</span> {</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span> {
            Log4jConfigurer.initLogging(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"classpath:log4j.properties"</span>);
        } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span> (FileNotFoundException ex) {
            System.err.println(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Cannot Initialize log4j"</span>);
            System.exit(-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);
        }
    }

    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 日志
     */</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> Log LOGGER = LogFactory.getLog(TestZookeeperAgainst.class);

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> ZooKeeper zk;

    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 代表“我”创建的子节点
     */</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> String myChildNodeName;

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">main</span>(String[] args) <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">throws</span> Exception {
        TestZookeeperAgainst testZookeeperAgainst = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> TestZookeeperAgainst();
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Thread(testZookeeperAgainst).start();
    }

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">TestZookeeperAgainst</span>() <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">throws</span> Exception {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.zk = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ZooKeeper(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"192.168.61.129:2181,192.168.61.130:2181,192.168.61.132:2181"</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">7200000</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> DefaultWatcher());

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//创建一个父级节点filesq(如果没有的话)</span>
        Stat pathStat = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>;
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span> {
            pathStat = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.zk.exists(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"/filesq"</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>);
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//2.2如果条件成立,说明节点不存在(只需要判断一个节点的存在性即可)</span>
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(pathStat == <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.zk.create(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"/filesq"</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">""</span>.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
            }
        } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span>(Exception e) {
            TestZookeeperAgainst.LOGGER.error(e.getMessage(), e);
            System.exit(-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);
        }
    }

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">run</span>() {
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/*
         * 当这个线程活动时,我们做以下几个事情:
         * 1、首先注册/filesq,检控/filesq下子节点的变化
         * 2、向/filesq中注册一个临时的,带有唯一编号的子节点,
         * 3、然后等待,直到AgainstWatcher发现已经轮到“自己”执行,并唤醒
         * 4、唤醒后,开始执行具体的业务。
         * 5、执行完成后,主动删除这个子节点, 或者剥离与zk的连接(推荐前者,但怎么操作,还是根据业务来)
         * */</span>

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//1、==============</span>
        String childPath = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"/filesq/childnode"</span>;
        AgainstWatcher againstWatcher = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> AgainstWatcher(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>);
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span> {
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//建立监听</span>
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.zk.getChildren(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"/filesq"</span>, againstWatcher);
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//2、==============</span>
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.myChildNodeName = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.zk.create(childPath, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">""</span>.getBytes(), 
                    Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
        } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span> (Exception e) {
            TestZookeeperAgainst.LOGGER.error(e.getMessage(), e);
            System.exit(-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);
        }
        TestZookeeperAgainst.LOGGER.info(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"被创建的子节点是:"</span> + <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.myChildNodeName);

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//3、==============</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">synchronized</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>) {
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span> {
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.wait();
            } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span> (InterruptedException e) {
                TestZookeeperAgainst.LOGGER.error(e.getMessage(), e);
                System.exit(-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);
            }
        }

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//4、==============</span>
        TestZookeeperAgainst.LOGGER.info(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"唤醒后,开始执行具体的业务========="</span>);

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//5、==============</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span> {
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.zk.delete(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.myChildNodeName, -<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);
        } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span> (Exception e) {
            TestZookeeperAgainst.LOGGER.error(e.getMessage(), e);
            System.exit(-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);
        }
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//this.zk.close();</span>

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//下面这段代码完全可以在正式使用时忽略,完全是为了观察zk的原理</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">synchronized</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>) {
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span> {
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.wait();
            } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span> (InterruptedException e) {
                TestZookeeperAgainst.LOGGER.error(e.getMessage(), e);
                System.exit(-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);
            }
        }
    }

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> String <span class="hljs-title" style="box-sizing: border-box;">getMyChildNodeName</span>() {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> myChildNodeName;
    }

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> ZooKeeper <span class="hljs-title" style="box-sizing: border-box;">getZk</span>() {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> zk;
    }
}

<span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
 * 这个watcher专门用来监听子级节点的变化
 *<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @author</span> yinwenjie
 */</span>
class AgainstWatcher implements Watcher {

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> Log LOGGER = LogFactory.getLog(AgainstWatcher.class);

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> TestZookeeperAgainst parentThread;

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">AgainstWatcher</span>(TestZookeeperAgainst parentThread) {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.parentThread = parentThread;
    }

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">process</span>(WatchedEvent event) {
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/*
         * 作为znode观察者,需要做以下事情:
         * 1、当收到一个监听事件后,要马上重新注册zk,以便保证下次事件监听能被接受
         * 2、比较当前/filesq下最小的一个节点A,如果这个节点A不是自己创建的,
         *      说明还不到自己执行,忽略后续操作
         * 3、如果A是自己创建的,则说明轮到自己占有这个资源了,唤醒parentThread进行业务处理
         * */</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//1、=========================</span>
        ZooKeeper zk = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.parentThread.getZk();
        List<String> childPaths = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>;
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span> {
            childPaths = zk.getChildren(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"/filesq"</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>);
        } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span> (Exception e) {
            AgainstWatcher.LOGGER.error(e.getMessage(), e);
            System.exit(-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);
        }
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(event.getType() != EventType.NodeChildrenChanged || childPaths == <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span> || childPaths.size() == <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) {
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span>;
        }

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//2、=========================</span>
        String nowPath = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"/filesq/"</span> + childPaths.get(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>);
        String myChildNodeName = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.parentThread.getMyChildNodeName();
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(!StringUtils.equals(nowPath, myChildNodeName)) {
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span>;
        }

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//3、=========================</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">synchronized</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.parentThread) {
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.parentThread.notify();
        }
    }
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li><li style="box-sizing: border-box; padding: 0px 5px;">72</li><li style="box-sizing: border-box; padding: 0px 5px;">73</li><li style="box-sizing: border-box; padding: 0px 5px;">74</li><li style="box-sizing: border-box; padding: 0px 5px;">75</li><li style="box-sizing: border-box; padding: 0px 5px;">76</li><li style="box-sizing: border-box; padding: 0px 5px;">77</li><li style="box-sizing: border-box; padding: 0px 5px;">78</li><li style="box-sizing: border-box; padding: 0px 5px;">79</li><li style="box-sizing: border-box; padding: 0px 5px;">80</li><li style="box-sizing: border-box; padding: 0px 5px;">81</li><li style="box-sizing: border-box; padding: 0px 5px;">82</li><li style="box-sizing: border-box; padding: 0px 5px;">83</li><li style="box-sizing: border-box; padding: 0px 5px;">84</li><li style="box-sizing: border-box; padding: 0px 5px;">85</li><li style="box-sizing: border-box; padding: 0px 5px;">86</li><li style="box-sizing: border-box; padding: 0px 5px;">87</li><li style="box-sizing: border-box; padding: 0px 5px;">88</li><li style="box-sizing: border-box; padding: 0px 5px;">89</li><li style="box-sizing: border-box; padding: 0px 5px;">90</li><li style="box-sizing: border-box; padding: 0px 5px;">91</li><li style="box-sizing: border-box; padding: 0px 5px;">92</li><li style="box-sizing: border-box; padding: 0px 5px;">93</li><li style="box-sizing: border-box; padding: 0px 5px;">94</li><li style="box-sizing: border-box; padding: 0px 5px;">95</li><li style="box-sizing: border-box; padding: 0px 5px;">96</li><li style="box-sizing: border-box; padding: 0px 5px;">97</li><li style="box-sizing: border-box; padding: 0px 5px;">98</li><li style="box-sizing: border-box; padding: 0px 5px;">99</li><li style="box-sizing: border-box; padding: 0px 5px;">100</li><li style="box-sizing: border-box; padding: 0px 5px;">101</li><li style="box-sizing: border-box; padding: 0px 5px;">102</li><li style="box-sizing: border-box; padding: 0px 5px;">103</li><li style="box-sizing: border-box; padding: 0px 5px;">104</li><li style="box-sizing: border-box; padding: 0px 5px;">105</li><li style="box-sizing: border-box; padding: 0px 5px;">106</li><li style="box-sizing: border-box; padding: 0px 5px;">107</li><li style="box-sizing: border-box; padding: 0px 5px;">108</li><li style="box-sizing: border-box; padding: 0px 5px;">109</li><li style="box-sizing: border-box; padding: 0px 5px;">110</li><li style="box-sizing: border-box; padding: 0px 5px;">111</li><li style="box-sizing: border-box; padding: 0px 5px;">112</li><li style="box-sizing: border-box; padding: 0px 5px;">113</li><li style="box-sizing: border-box; padding: 0px 5px;">114</li><li style="box-sizing: border-box; padding: 0px 5px;">115</li><li style="box-sizing: border-box; padding: 0px 5px;">116</li><li style="box-sizing: border-box; padding: 0px 5px;">117</li><li style="box-sizing: border-box; padding: 0px 5px;">118</li><li style="box-sizing: border-box; padding: 0px 5px;">119</li><li style="box-sizing: border-box; padding: 0px 5px;">120</li><li style="box-sizing: border-box; padding: 0px 5px;">121</li><li style="box-sizing: border-box; padding: 0px 5px;">122</li><li style="box-sizing: border-box; padding: 0px 5px;">123</li><li style="box-sizing: border-box; padding: 0px 5px;">124</li><li style="box-sizing: border-box; padding: 0px 5px;">125</li><li style="box-sizing: border-box; padding: 0px 5px;">126</li><li style="box-sizing: border-box; padding: 0px 5px;">127</li><li style="box-sizing: border-box; padding: 0px 5px;">128</li><li style="box-sizing: border-box; padding: 0px 5px;">129</li><li style="box-sizing: border-box; padding: 0px 5px;">130</li><li style="box-sizing: border-box; padding: 0px 5px;">131</li><li style="box-sizing: border-box; padding: 0px 5px;">132</li><li style="box-sizing: border-box; padding: 0px 5px;">133</li><li style="box-sizing: border-box; padding: 0px 5px;">134</li><li style="box-sizing: border-box; padding: 0px 5px;">135</li><li style="box-sizing: border-box; padding: 0px 5px;">136</li><li style="box-sizing: border-box; padding: 0px 5px;">137</li><li style="box-sizing: border-box; padding: 0px 5px;">138</li><li style="box-sizing: border-box; padding: 0px 5px;">139</li><li style="box-sizing: border-box; padding: 0px 5px;">140</li><li style="box-sizing: border-box; padding: 0px 5px;">141</li><li style="box-sizing: border-box; padding: 0px 5px;">142</li><li style="box-sizing: border-box; padding: 0px 5px;">143</li><li style="box-sizing: border-box; padding: 0px 5px;">144</li><li style="box-sizing: border-box; padding: 0px 5px;">145</li><li style="box-sizing: border-box; padding: 0px 5px;">146</li><li style="box-sizing: border-box; padding: 0px 5px;">147</li><li style="box-sizing: border-box; padding: 0px 5px;">148</li><li style="box-sizing: border-box; padding: 0px 5px;">149</li><li style="box-sizing: border-box; padding: 0px 5px;">150</li><li style="box-sizing: border-box; padding: 0px 5px;">151</li><li style="box-sizing: border-box; padding: 0px 5px;">152</li><li style="box-sizing: border-box; padding: 0px 5px;">153</li><li style="box-sizing: border-box; padding: 0px 5px;">154</li><li style="box-sizing: border-box; padding: 0px 5px;">155</li><li style="box-sizing: border-box; padding: 0px 5px;">156</li><li style="box-sizing: border-box; padding: 0px 5px;">157</li><li style="box-sizing: border-box; padding: 0px 5px;">158</li><li style="box-sizing: border-box; padding: 0px 5px;">159</li><li style="box-sizing: border-box; padding: 0px 5px;">160</li><li style="box-sizing: border-box; padding: 0px 5px;">161</li><li style="box-sizing: border-box; padding: 0px 5px;">162</li><li style="box-sizing: border-box; padding: 0px 5px;">163</li><li style="box-sizing: border-box; padding: 0px 5px;">164</li><li style="box-sizing: border-box; padding: 0px 5px;">165</li><li style="box-sizing: border-box; padding: 0px 5px;">166</li><li style="box-sizing: border-box; padding: 0px 5px;">167</li><li style="box-sizing: border-box; padding: 0px 5px;">168</li><li style="box-sizing: border-box; padding: 0px 5px;">169</li><li style="box-sizing: border-box; padding: 0px 5px;">170</li><li style="box-sizing: border-box; padding: 0px 5px;">171</li><li style="box-sizing: border-box; padding: 0px 5px;">172</li><li style="box-sizing: border-box; padding: 0px 5px;">173</li><li style="box-sizing: border-box; padding: 0px 5px;">174</li><li style="box-sizing: border-box; padding: 0px 5px;">175</li><li style="box-sizing: border-box; padding: 0px 5px;">176</li></ul>

4、后文介绍

和实验室各位大神讨论zookeeper的时间是8月13号,借这个机会我在Blog上面预发布了hadoop系列的zookeeper文章3篇。相信各位读者对zookeeper已经有一个大致了解,并能够将其运用到自己的工作中了(还是那句话,网上的文章不能全信,实践才是检验真理的唯一标准)。

这篇文章后,我会将写作重点移回 架构设计:负载均衡层设计方案 系列文章,毕竟还差一篇 LVS + Keepalived + Nginx的整合文章,负载均衡层的介绍就可以告一段落了。在后面就是业务层的介绍了,我将重点介绍两种消息队列和两套SOA实现方案(我想,什么Tomcat的优化、Spring的使用等等基础知识,就不需要写了吧。。),再次感谢各位对我博客的关注。

最后推荐几篇阿里团队关于zookeeper的文章:

《ZooKeeper的一个性能测试》:http://jm-blog.aliapp.com/?p=1070 
《ZooKeeper问题汇总》:http://jm-blog.aliapp.com/?p=1384 
《ZooKeeper监控》:http://jm-blog.aliapp.com/?p=1450

相关文章推荐

hadoop系列:zookeeper(3)——zookeeper核心原理(事件)

上一篇文章,我们对zookeeper中的数据组织结构、Leader选举原理进行了讲述。这篇文章我们紧接上文讲解zookeeper中的事件机制。并通过示例代码告诉读者怎么使用zookeeper中的事件通...

hadoop系列:zookeeper(2)——zookeeper核心原理(选举)

前述上篇文章《hadoop系列:zookeeper(1)——zookeeper单点和集群安装》(http://blog.csdn.net/yinwenjie/article/details/47361...

Hadoop Hbase Zookeeper系列安装手册

  • 2016年05月14日 13:23
  • 620KB
  • 下载

ZooKeeper 核心模块工作原理分析

工作原理概述 简单的说一下zookeeper工作的过程,如果对这个过程还不太清楚,或者说对它如何使用等不太清楚的,可以参考一下其他的文章,比如这篇,这一系列的文章将不讲解它如何使用(实际上我也没有在具...

【Apache Nutch系列】Nutch2.2+hadoop+hbase+zookeeper环境部署

1、下载数据包 wget http://archive.apache.org/dist/hbase/hbase-0.90.4/hbase-0.90.4.tar.gz wget http://arc...

Distributed System: ZooKeeper系列之四 (Hadoop和HBase的应用)

这期文章,参考Linux 爱好者公众号的文章《ZooKeeper原理及其在Hadoop和Hbase中的应用》而归纳整理的。 理解一下内容之前,先提一句,ZooKeeper节点一般不与Mast...

Hadoop系列之(三)Zookeeper、HBase安装配置

Zookeeper管理Hadoop集群中的NameNode,HBase中HBaseMaster的选举,Servers之间状态同步等。单只HBase中ZooKeeper实例负责的工作就有:存储HBase...

ZooKeeper原理及其在Hadoop和HBase中的应用

ZooKeeper是一个开源的分布式协调服务,由雅虎创建,是Google Chubby的开源实现。分布式应用程序可以基于ZooKeeper实现诸如数据发布/订阅、负载均衡、命名服务、分布式协调/通知、...

ZooKeeper 原理及其在 Hadoop 和 HBase 中的应用

ZooKeeper是一个开源的分布式协调服务,由雅虎创建,是Google Chubby的开源实现。分布式应用程序可以基于ZooKeeper实现诸如数据发布/订阅、负载均衡、命名服务、分布式协调/通知、...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:hadoop系列:zookeeper(3)——zookeeper核心原理(事件)
举报原因:
原因补充:

(最多只允许输入30个字)