集群机器监控:这通常用于那种对集群中机器状态,机器在线率有较高要求的场景,能够快速对集群中机器变化作出响应。这样的场景中,往往有一个监控系统,实时检测集群机器是否存活。过去的做法通常是:监控系统通过某种手段(比如ping)定时检测每个机器,或者每个机器自己定时向监控系统汇报“我还活着”。 这种做法可行,但是存在两个比较明显的问题:1、集群中的机器有变动时,牵连修改的东西比较多;2、有一定的延时(来自:http://www.cnblogs.com/ggjucheng/p/3352614.html)。
Zookeeper同样很容易实现这个功能,比如我在zookeeper服务器端有一个znode叫/APP1SERVERS,那么集群中每一个机器启动的时候都去这个节点下创建一个EPHEMERAL类型的节点,比如server1创建/APP1SERVERS/SERVER1(可以使用ip,保证不重复),server2创建/APP1SERVERS/SERVER2,然后SERVER1和SERVER2都watch /APP1SERVERS这个父节点,那么也就是这个父节点下数据或者子节点变化都会通知对该节点进行watch的客户端。因为EPHEMERAL类型节点有一个很重要的特性,就是客户端和服务器端连接断掉或者session过期就会使节点消失,那么在某一个机器挂掉或者断链的时候,其对应的节点就会消失,然后集群中所有对/APP1SERVERS进行watch的客户端都会收到通知,然后取得最新列表即可。(来自:http://cailin.iteye.com/blog/2014486)
下面是组关系管理的例子:
如果运行:
1、下载代码:https://github.com/sleberknight/zookeeper-samples/tree/master/src/main/java/com/nearinfinity/examples/zookeeper
2、下载zookeeper-3.4.*.tar.gz源码包,导入jar包:log4j,slf4j-api,slf4j-log4j,zooKeeper-四个jar包。
1、监听组变化
ZooKeeper客户端中需要处理来自服务端的两类事件通知:一类是Watches时间通知,另一类则是异步接口调用的响应,在ZooKeeper的客户端线程模型中,这两个事件由同一个线程处理,并且是串行处理。下面是使用异步接口相应的例子:应用注册了对某znode子节点列表变化的监听,逻辑是在接受到ZooKeeper服务器节点列表变更通知(EventType.NodeChildrenChanged)的时候,进行一些操作。
package com.nearinfinity.examples.zookeeper.group;
import com.nearinfinity.examples.zookeeper.util.ConnectionWatcher;
import org.apache.zookeeper.AsyncCallback;
import org.apache.zookeeper.KeeperException;
import java.util.List;
import java.util.concurrent.CountDownLatch;
public class AsyncListGroup extends ConnectionWatcher {
public static void main(String[] args) throws Exception {
AsyncListGroup asyncListGroup = new AsyncListGroup();
asyncListGroup.connect(args[0]);
asyncListGroup.list(args[1]);
asyncListGroup.close();
}
public void list(final String groupName) throws KeeperException, InterruptedException {
String path = "/" + groupName;
// In real code, you would not use the async API the way it's being used here. You would
// go off and do other things without blocking like this example does.
final CountDownLatch latch = new CountDownLatch(1);
zk.getChildren(path, false,
new AsyncCallback.ChildrenCallback() {
@Override
public void processResult(int rc, String path, Object ctx, List<String> children) {
System.out.printf("Called back for path %s with return code %d\n", path, rc);
if (children == null) {
System.out.printf("Group %s does not exist\n", groupName);
} else {
if (children.isEmpty()) {
System.out.printf("No members in group %s\n", groupName);
return;
}
for (String child : children) {
System.out.println(child);
}
}
latch.countDown();
}
}, null /* optional context object */);
System.out.println("Awaiting latch countdown...");
latch.await();
}
}
2、创建组
创建的是一个持久性的节点
package com.nearinfinity.examples.zookeeper.group;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.ZooKeeper;
public class CreateGroup implements Watcher {
private static final int SESSION_TIMEOUT = 5000;
private ZooKeeper _zk;
private CountDownLatch _connectedSignal = new CountDownLatch(1);
public void connect(String hosts) throws IOException, InterruptedException {
_zk = new ZooKeeper(hosts, SESSION_TIMEOUT, this);
_connectedSignal.await();
}
@Override
public void process(WatchedEvent event) { // Watcher interface
if (event.getState() == Event.KeeperState.SyncConnected) {
System.out.println("Connected...");
_connectedSignal.countDown();
}
}
public void create(String groupName) throws KeeperException, InterruptedException {
String path = "/" + groupName;
String createdPath = _zk.create(path,
null /*data*/,
ZooDefs.Ids.OPEN_ACL_UNSAFE,
CreateMode.PERSISTENT);
System.out.println("Created " + createdPath);
}
public void close() throws InterruptedException {
_zk.close();
}
public static void main(String[] args) throws Exception {
CreateGroup createGroup = new CreateGroup();
createGroup.connect(args[0]);
createGroup.create(args[1]);
createGroup.close();
}
}
3、删除组
package com.nearinfinity.examples.zookeeper.group;
import java.util.List;
import org.apache.zookeeper.KeeperException;
import com.nearinfinity.examples.zookeeper.util.ConnectionWatcher;
public class DeleteGroup extends ConnectionWatcher {
public void delete(String groupName) throws KeeperException, InterruptedException {
String path = "/" + groupName;
try {
List<String> children = zk.getChildren(path, false);
for (String child : children) {
zk.delete(path + "/" + child, -1);
}
zk.delete(path, -1);
System.out.printf("Deleted group %s at path %s\n", groupName, path);
}
catch (KeeperException.NoNodeException e) {
System.out.printf("Group %s does not exist\n", groupName);
}
}
public static void main(String[] args) throws Exception {
DeleteGroup deleteGroup = new DeleteGroup();
deleteGroup.connect(args[0]);
deleteGroup.delete(args[1]);
deleteGroup.close();
}
}
4、遍历某个组内成员
package com.nearinfinity.examples.zookeeper.group;
import java.io.IOException;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Semaphore;
import com.nearinfinity.examples.zookeeper.util.ConnectionHelper;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
public class GroupMembershipIterable implements Iterable<List<String>> {
private ZooKeeper _zooKeeper;
private String _groupName;
private String _groupPath;
private Semaphore _semaphore = new Semaphore(1);
public static void main(String[] args) throws IOException, InterruptedException {
ZooKeeper zk = new ConnectionHelper().connect(args[0]);
String theGroupName = args[1];
GroupMembershipIterable iterable = new GroupMembershipIterable(zk, theGroupName);
Iterator<List<String>> iterator = iterable.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
System.out.println("--------------------");
}
System.out.printf("Group %s does not exist (anymore)!", theGroupName);
}
public GroupMembershipIterable(ZooKeeper zooKeeper, String groupName) {
_zooKeeper = zooKeeper;
_groupName = groupName;
_groupPath = pathFor(groupName);
}
@Override
public Iterator<List<String>> iterator() {
return new Iterator<List<String>>() {
@Override
public boolean hasNext() {
try {
_semaphore.acquire();
return _zooKeeper.exists(_groupPath, false) != null;
} catch (InterruptedException e) {
throw new RuntimeException(e);
} catch (KeeperException e) {
throw new RuntimeException(e);
}
}
@Override
public List<String> next() {
try {
return list(_groupName);
} catch (InterruptedException e) {
throw new RuntimeException(e);
} catch (KeeperException e) {
throw new RuntimeException(e);
}
}
@Override
public void remove() {
throw new UnsupportedOperationException("Removing znodes not supported");
}
};
}
private List<String> list(final String groupName) throws KeeperException, InterruptedException {
String path = pathFor(groupName);
List<String> children = _zooKeeper.getChildren(path, new Watcher() {
@Override
public void process(WatchedEvent event) {
if (event.getType() == Event.EventType.NodeChildrenChanged) {
_semaphore.release();
} else if (event.getType() == Event.EventType.NodeDeleted && event.getPath().equals(_groupPath)) {
_semaphore.release();
}
}
});
Collections.sort(children);
return children;
}
private String pathFor(String groupName) {
return "/" + groupName;
}
}
5、加入组
package com.nearinfinity.examples.zookeeper.group;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.ZooDefs;
import com.nearinfinity.examples.zookeeper.util.ConnectionWatcher;
public class JoinGroup extends ConnectionWatcher {
public void join(String groupName, String memberName) throws KeeperException, InterruptedException {
String path = "/" + groupName + "/" + memberName;
String createdPath = zk.create(path,
null/*data*/,
ZooDefs.Ids.OPEN_ACL_UNSAFE,
CreateMode.EPHEMERAL);
System.out.println("Created " + createdPath);
}
public static void main(String[] args) throws Exception {
JoinGroup joinGroup = new JoinGroup();
joinGroup.connect(args[0]);
joinGroup.join(args[1], args[2]);
// stay alive until process is killed or thread is interrupted
Thread.sleep(Long.MAX_VALUE);
}
}
6 访问一次组内成员
package com.nearinfinity.examples.zookeeper.group;
import java.util.List;
import org.apache.zookeeper.KeeperException;
import com.nearinfinity.examples.zookeeper.util.ConnectionWatcher;
public class ListGroup extends ConnectionWatcher {
public void list(String groupName) throws KeeperException, InterruptedException {
String path = "/" + groupName;
try {
List<String> children = zk.getChildren(path, false);
if (children.isEmpty()) {
System.out.printf("No members in group %s\n", groupName);
return;
}
for (String child : children) {
System.out.println(child);
}
}
catch (KeeperException.NoNodeException e) {
System.out.printf("Group %s does not exist\n", groupName);
}
}
public static void main(String[] args) throws Exception {
ListGroup listGroup = new ListGroup();
listGroup.connect(args[0]);
listGroup.list(args[1]);
listGroup.close();
}
}
7永久访问组内成员
package com.nearinfinity.examples.zookeeper.group;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Semaphore;
import com.nearinfinity.examples.zookeeper.util.ConnectionHelper;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
public class ListGroupForever {
private ZooKeeper _zooKeeper;
private Semaphore _semaphore = new Semaphore(1);
public ListGroupForever(ZooKeeper zooKeeper) {
_zooKeeper = zooKeeper;
}
public static void main(String[] args) throws Exception {
ZooKeeper zk = new ConnectionHelper().connect(args[0]);
new ListGroupForever(zk).listForever(args[1]);
}
public void listForever(String groupName) throws KeeperException, InterruptedException {
_semaphore.acquire();
while (true) {
list(groupName);
_semaphore.acquire();
}
}
private void list(String groupName) throws KeeperException, InterruptedException {
String path = "/" + groupName;
List<String> children = _zooKeeper.getChildren(path, new Watcher() {
@Override
public void process(WatchedEvent event) {
if (event.getType() == Event.EventType.NodeChildrenChanged) {
_semaphore.release();
} } });
if (children.isEmpty()) {
System.out.printf("No members in group %s\n", groupName);
return;
}
Collections.sort(children);
System.out.println(children);
System.out.println("--------------------");
}
}