for(Stringstr:
nodeListNow){
if(!
nodeListBefore.contains(str)){
Log.info("新增加的节点是:
"+event.getPath()+"/"+str);
}
}
}
}
};
}
publicvoidmonitorNodes(Watcherwc)throwsInterruptedException{
for(;;){
try{
zooKeeper.exists(getMonitorNode(),wc);//所要监控的主结点
}catch(Exceptione){
Log.error(e);
}
Thread.sleep(3000);//
try{
nodeList=zooKeeper.getChildren(getMonitorNode(),wc);
for(Stringchild:
nodeList){
Log.info(getMonitorNode()+"的子节点有:
"+child);
}
}catch(Exceptione){
Log.error(e);
}
Thread.sleep(3000);
//对PATH下的每个结点都设置一个watcher
if(null!
=nodeList&&nodeList.size()>0){
for(StringnodeName:
nodeList){
try{
zooKeeper.exists(getMonitorNode()+"/"+nodeName,wc);
}catch(Exceptione){
Log.error(e);
}
}
}
}
}
/**
*
*获取节点数据
*
*/
publicbyte[]getData(Stringpath)throwsKeeperException,InterruptedException{
returnthis.zooKeeper.getData(path,false,null);
}
publicstaticvoidmain(String[]args){
newThread(newZKNodeWatcher("/node")).start();
}
}
importjava.io.IOException;
importjava.util.concurrent.CountDownLatch;
importorg.apache.log4j.Logger;
importorg.apache.zookeeper.WatchedEvent;
importorg.apache.zookeeper.Watcher;
importorg.apache.zookeeper.Watcher.Event.KeeperState;
importorg.apache.zookeeper.ZooKeeper;
/**
*
*@authorhadoop
*
*/
publicclassAbstractZooKeeperimplementsWatcher{
protectedLoggerlogger=Logger.getLogger(AbstractZooKeeper.class);
//缓存时间
privatestaticfinalintSESSION_TIME=2000;
protectedZooKeeperzooKeeper;
protectedCountDownLatchcountDownLatch=newCountDownLatch
(1);
//连接zk集群
publicvoidconnect(Stringhosts)throwsIOException,InterruptedException{
zooKeeper=newZooKeeper(hosts,SESSION_TIME,this);
countDownLatch.await();
}
//zk处理
@Override
publicvoidprocess(WatchedEventevent){
if(event.getState()==KeeperState.SyncConnected){
countDownLatch.countDown();
}
System.out.println("已经触发了"+event.getType()+"事件!
");
}
//关闭集群
publicvoidclose()throwsInterruptedException{
zooKeeper.close();
}
}
运行之后,客户端一直在监测zookeeper集群的节点情况
在另外客户端进行新建节点操作
API均能监测到节点变化信息
2、zookeeper的ACL实践
ØWorld模式
ØAuth模式
ØDigest模式
ØIP模式
ØSuper模式
由于使用super模式其用户名以及密码需要经过sha1和base64转码,利用以下的Java代码实现加密转码。
importjava.io.IOException;
importjava.security.MessageDigest;
importjava.security.NoSuchAlgorithmException;
importorg.apache.zookeeper.KeeperException;
/**
*
*@authorhadoop
*
*/
publicclassSuperAcl{
publicstaticvoidmain(String[]args)throwsIOException,InterruptedException,KeeperException{
Stringpasswd="super:
admin123";
System.out.println(generateDigest(passwd));
}
staticpublicStringgenerateDigest(StringidPassword){
Stringparts[]=idPassword.split(":
",2);
bytedigest[]=null;
try{
digest=MessageDigest.getInstance("SHA1").digest(idPassword.getBytes());
}catch(NoSuchAlgorithmExceptione){
e.printStackTrace();
}
returnparts[0]+":
"+base64Encode(digest);
}
staticfinalprivateStringbase64Encode(byteb[]){
StringBuildersb=newStringBuilder();
for(inti=0;iintpad=0;
intv=(b[i++]&0xff)<<16;
if(iv|=(b[i++]&0xff)<<8;
}else{
pad++;
}
if(iv|=(b[i++]&0xff);
}else{
pad++;
}
sb.append(encode(v>>18));
sb.append(encode(v>>12));
if(pad<2){
sb.append(encode(v>>6));
}else{
sb.append('=');
}
if(pad<1){
sb.append(encode(v));
}else{
sb.append('=');
}
}
returnsb.toString();
}
staticfinalprivatecharencode(inti){
i&=0x3f;
if(i<26){
return(char)('A'+i);
}
if(i<52){
return(char)('a'+i-26);
}
if(i<62){
return(char)('0'+i-52);
}
returni==62?
'+':
'/';
}
}
修改Zookeeper的启动脚本zkServer.sh,在start附件(100行左右)加入以下配置:
-Dzookeeper.DigestAuthenticationProvider.superDigest=super:
/o7XEyClGiOcKnJmPVFVYU8AQdw=
重新启动Zookeeper服务:
zkServer.shrestart
使用super:
admin123连接Zookeeper服务器就可以对里面的节点任意妄为了。