Java客户端编写良好的Zookeeper Hello World程序

5

我正在尝试在我们的项目中使用Zookeeper。可以运行服务器..甚至使用zkcli.sh进行测试..一切正常.. 但是我找不到一个好的教程,告诉我如何使用Java连接到这个服务器!在Java API中,我所需要的只是一个方法

public String getServiceURL ( String serviceName ) 

我尝试了https://cwiki.apache.org/confluence/display/ZOOKEEPER/Index,但对我来说不好用。 http://zookeeper.apache.org/doc/trunk/javaExample.html:还行,但是无法清楚地理解概念!我觉得它的解释不够清晰。

2
也许您应该重新表达您的问题,并避免使用“教程”这个词汇;-) - Marged
3
我认为这个问题可以通过重新提问来更好地表达,比如询问“我的Zookeeper Hello World程序有什么问题?”,并在问题中附上示例代码,并引用您目前已经拥有的现有参考资料。 - entpnerd
2
不知道有谁会否认这个问题。下面由同一人提供的问题和答案对我帮助很大!谢谢Deepak!!! - Erikson
5个回答

30

最后,这是我想出的最简单和基础的程序,它将帮助你开始使用ZooKeeper:

package core.framework.zookeeper;

import java.util.Date;
import java.util.List;
import java.util.concurrent.CountDownLatch;

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;

public class ZkConnect {
    private ZooKeeper zk;
    private CountDownLatch connSignal = new CountDownLatch(0);

    //host should be 127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002
    public ZooKeeper connect(String host) throws Exception {
        zk = new ZooKeeper(host, 3000, new Watcher() {
            public void process(WatchedEvent event) {
                if (event.getState() == KeeperState.SyncConnected) {
                    connSignal.countDown();
                }
            }
        });
        connSignal.await();
        return zk;
    }

    public void close() throws InterruptedException {
        zk.close();
    }

    public void createNode(String path, byte[] data) throws Exception
    {
        zk.create(path, data, Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
    }

    public void updateNode(String path, byte[] data) throws Exception
    {
        zk.setData(path, data, zk.exists(path, true).getVersion());
    }

    public void deleteNode(String path) throws Exception
    {
        zk.delete(path,  zk.exists(path, true).getVersion());
    }

    public static void main (String args[]) throws Exception
    {
        ZkConnect connector = new ZkConnect();
        ZooKeeper zk = connector.connect("54.169.132.0,52.74.51.0");
        String newNode = "/deepakDate"+new Date();
        connector.createNode(newNode, new Date().toString().getBytes());
        List<String> zNodes = zk.getChildren("/", true);
        for (String zNode: zNodes)
        {
           System.out.println("ChildrenNode " + zNode);   
        }
        byte[] data = zk.getData(newNode, true, zk.exists(newNode, true));
        System.out.println("GetData before setting");
        for ( byte dataPoint : data)
        {
            System.out.print ((char)dataPoint);
        }

        System.out.println("GetData after setting");
        connector.updateNode(newNode, "Modified data".getBytes());
        data = zk.getData(newNode, true, zk.exists(newNode, true));
        for ( byte dataPoint : data)
        {
            System.out.print ((char)dataPoint);
        }
        connector.deleteNode(newNode);
    }

}

4
谢谢提供示例。需要注意的是,默认情况下,您需要将CountDownLatch设置为非0值,因为.await()方法会在计数器达到0时返回,而0是默认值。如果在event.getState() == KeeperState.SyncConnected时将其设置为1,则会启动计时器,并在1个时间间隔后达到0,从而返回zk。 - ammills01
主机在主方法中传递给连接,因为没有指定端口,所以这样做是否有误? - JSR29
@JSR29 Zookeeper 假定您正在使用 2181。 - Ben Watson
这段代码是死锁的。有人成功解决了吗?watcher.process在remove latch.await之后执行。 - Yin

6

3
这是一个非常简单的例子。我正在构建一个工具,它将使用ZK来锁定正在处理的文件(这就是类名的含义):
package mypackage;

import java.io.IOException;
import java.util.List;

import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.Watcher;

public class ZooKeeperFileLock {

  public static void main(String[] args) throws IOException, KeeperException, InterruptedException {

    String zkConnString = "<zknode1>:2181,<zknode2>:2181,<zknode3>:2181";

    ZooKeeperWatcher zkWatcher = new ZooKeeperWatcher();
    ZooKeeper client = new ZooKeeper(zkConnString, 10000, zkWatcher);

    List<String> zkNodes = client.getChildren("/", true);

    for(String node : zkNodes) {
      System.out.println(node);
    }
  }

  public static class ZooKeeperWatcher implements Watcher {

    @Override
    public void process(WatchedEvent event) {
    }

  }

3
哇,为什么会被踩呢?这个列表展示了ZK Chroot目录中的所有节点,非常简单易懂。但我该如何知道是谁踩了我?在踩完之后请先澄清再离开。 - Chris C
1
我给了你点赞:)。这对我很有帮助。有时候人们会毫无解释地踩你的帖子。我也遇到过同样的情况。 - Kumar
你实际上没有使用任何文件。我认为你的程序只是列出了根 znode。 - Mehdi LAMRANI
是的,我可以编辑。那只是我在编写实际程序时使用的存根代码。谢谢你提醒我。 - Chris C
"会话建立是异步的。您不需要等待与Zookeeper的连接建立。" - andresp
请查看已接受的答案并了解CountDownLatch的作用。 - andresp

3
此博客文章《Zookeeper Java API examples》提供了一些很好的Java示例,如果您正在寻找Java示例来开始使用。Zookeeper还提供了一个客户端API库(C和Java),非常易于使用。
Zookeeper是最好的开源服务器和服务之一,可以可靠地协调分布式进程。 Zookeeper是一个CP系统(参考CAP定理),提供一致性和分区容错性。在所有节点上复制Zookeeper状态使其成为一种最终一致的分布式服务。

2

如果您在使用AWS,现在我们可以创建支持基于URI重定向的内部ELB,这可以很好地解决高可用性问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接