成员列表

下面我们实现一个程序来列出一个组中的所有成员。

  1. public class ListGroup extends ConnectionWatcher {
  2. public void list(String groupName) throws KeeperException,
  3. InterruptedException {
  4. String path = "/" + groupName;
  5. try {
  6. List<String> children = zk.getChildren(path, false);
  7. if (children.isEmpty()) {
  8. System.out.printf("No members in group %s\n", groupName);
  9. System.exit(1);
  10. }
  11. for (String child : children) {
  12. System.out.println(child);
  13. }
  14. } catch (KeeperException.NoNodeException e) {
  15. System.out.printf("Group %s does not exist\n", groupName);
  16. System.exit(1);
  17. }
  18. }
  19. public static void main(String[] args) throws Exception {
  20. ListGroup listGroup = new ListGroup();
  21. listGroup.connect(args[0]);
  22. listGroup.list(args[1]);
  23. listGroup.close();
  24. }
  25. }

我们在list()方法中通过调用getChildren()方法来获得某一个path下的子节点,然后打印出来。我们这里会试着捕获KeeperException.NoNodeException,当znode不存在时会抛出这个异常。我们运行程序,会看见如下结果,说明我们还没在zoo组中添加任何成员几点:

  1. % java ListGroup localhost zoo
  2. No members in group zoo

我们可以运行之前的JoinGroup来添加成员。在后台运行一些JoinGroup程序,这些程序添加节点后都处于sleep状态:

  1. % java JoinGroup localhost zoo duck &
  2. % java JoinGroup localhost zoo cow &
  3. % java JoinGroup localhost zoo goat &
  4. % goat_pid=$!

最后一行命令的作用是将最后一个启动的java程序的pid记录下来,我们好在列出zoo下面的成员后,将该进程kill掉。

下面我们将zoo下的成员打印出来:

  1. % java ListGroup localhost zoo
  2. goat
  3. duck
  4. cow

然后我们将kill掉最后启动的JoinGroup客户端:

  1. % kill $goat_pid

过几秒后,我们发现goat节点不见了。因为之前我们创建的goat节点是一个ephemeral节点,而创建这个节点的客户端在ZooKeeper上的会话已经被终结了,因为这个回话在5秒后失效了(我们设置了会话的超时时间为5秒):

  1. % java ListGroup localhost zoo
  2. duck
  3. cow

让我们回过头来看看,我们到底都做了一些什么?我们首先创建了一个节点组,这些节点的创建者都在同一个分布式系统中。这些节点的创建者之间互相都不知情。一个创建者想使用这些节点数据进行一些工作,例如通过znode节点是否存在来判断节点的创建者是否存在。

最后一点,我们不能只依靠组成员关系来完全解决在与节点通信时的网络错误。当与一个集群组成员节点进行通信时,发生了通信失败,我们需要使用重试或者试验与组中其他的节点通信,来解决这次通信失败。

Zookeeper的命令行工具

Zookeeper有一套命令行工具。我们可以像如下使用,来查找zoo下的成员节点:

  1. % zkCli.sh -server localhost ls /zoo
  2. [cow, duck]

你可以不加参数运行这个工具,来获得帮助。