集羣機器監控:這通常用於那種對集羣中機器狀態,機器在線率有較高要求的場景,能夠快速對集羣中機器變化作出響應。這樣的場景中,往往有一個監控系統,實時檢測集羣機器是否存活。過去的做法通常是:監控系統通過某種手段(比如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("--------------------");
}
}