从 Zookeeper 获取简单配置

Simple config fetching from Zookeeper

我必须从 Zookeeper 获取一些配置。 我现在做什么:

ZooKeeper zk = null;
try {
    zk = new ZooKeeper(zkConnect, 1000, null);
    byte[] fetched = zk.getData(CONFIG_ZNODE_PATH, false, null);
    zk.close();
    return deserializeProps(fetched);
} finally {
    if (zk != null) {
        zk.close();
    }
}

但我不确定我是否以正确的方式做这件简单的事情,因为在 doc 中指出:

Session establishment is asynchronous. This constructor will initiate connection to the server and return immediately - potentially (usually) before the session is fully established.

这是否意味着代码无效,我无法在构造函数调用后立即调用 getData

顺便说一句,运行代码时没有出现错误。

这里发生的是,zookeeper 在后台建立与 zookeeper 整体的连接。因此,当您调用您的方法来获取配置时,连接和会话已经正确建立。

只要你有一个完美的网络,zookeeper 客户端总是能够找到 zookeeper 服务器,这就可以正常工作。但是,如果您的客户端在一段时间内找不到 zookeeper 服务器,我猜这将抛出异常并且您的操作将失败。

为了解决这个问题,要么你必须等到 zookeeper 客户端连接如下,

private ZooKeeper zk;
final CountDownLatch connectionLatch = new CountDownLatch(1);

public void yourMethod() {

    zk = new ZooKeeper(zkConnect, 2000, new Watcher() {

        public void process(WatchedEvent we) {
            if (we.getState() == KeeperState.SyncConnected) {
                connectionLatch.countDown();
            }
        }
    });

    connectionLatch.await();

    // Now we have connected to zookeeper.
    // Now, we can fetch configuration safely.
    byte[] fetched = zk.getData(CONFIG_ZNODE_PATH, false, null);
    return deserializeProps(fetched);
}

记住你的方法没有错,只是不安全。在你的情况下,它运作良好。如果网络延迟很大,这可能不会像您预期的那样工作。我建议的是一种更安全的方法。

我使用 this blog post 中给出的代码来解释我的建议。你也可以参考一下,以便更好地理解。