Zookeeper与Curator
Zookeeper作为分布式应用程序的配置服务器使用,可以将动态配置的属性和信息放到zookeeper上,应用程序运行时从zookeeper上获取运行需要的配置信息,特别是,如果应用程序添加了对zk指定节点的监听,那么当zk上的配置动态变更后,会触发应用程序响应配置信息的更改。(在看下面的内容前,具体查看Hadoop权威指南的第十四章)。
1. Zk的常用命令
Zk的启动:
./zkServer.sh start
Zk的控制台连接
./zkCli.sh -server 127.0.0.1:2181
其它略。。。
2. ZK的java客户端连接
Zk提供了java的客户端,maven应用如下:
<</span>dependency>
<</span>groupId>org.apache.zookeeper</</span>groupId>
<</span>artifactId>zookeeper</</span>artifactId>
<</span>version>3.4.5</</span>version>
</</span>dependency>
可以使用zookeeper的java客户端完成对zk的操作。
下面一段代码描述了从指定zk上读取上面所有节点的例子:
public class ZKTracePrint implements Watcher{
private static final int SESSION_TIMEOUT = 5000;
private ZooKeeper zk;
private CountDownLatch latch = new CountDownLatch(1);
public void connection(String hosts) throws IOException, InterruptedException {
zk = new ZooKeeper(hosts, SESSION_TIMEOUT, this);//连接zk
latch.await();//等到zk连接完成
}
public void process(WatchedEvent event) {
if(event.getState() == KeeperState.SyncConnected)//zk连接完成
latch.countDown();//解锁
}
public void close() throws InterruptedException{
zk.close();
}
public void listTrace(String beginPath) throws IOException{
if(beginPath == null || "".equals(beginPath) || "/".equals(beginPath))
{
beginPath = "/";
}
listTrace(beginPath, "");
}
public void listTrace(String path,String deep) throws IOException{
deep = deep + " ";
System.out.println(path);
try {
List children = zk.getChildren(path, false);
byte[] data = zk.getData(path, false, null);
if(children.isEmpty()){
if(data == null)
return;
System.out.println(deep+new String(data));
}else{
if(data != null)
System.out.println(deep + new String(data));
for(String child: children){
if(!path.equals("/"))
listTrace(path+"/"+child,deep + " ");
else
listTrace(path+child,deep + " ");
}
}
} catch (KeeperException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void printZKTrance(String hosts) throws IOException, InterruptedException{
ZKTracePrint zk = new ZKTracePrint();
zk.connection(hosts);
zk.listTrace(null);
zk.close();
}
public static void main(String[] args) throws IOException, InterruptedException {
ZKTracePrint tool = new ZKTracePrint();
tool.printZKTrance("127.0.0.1:2181");
}
}
3. 使用Curator控制zk
Curator封装了Zk的java客户端,能够更加简单的控制zk,并具有对zk的重连机制。
Curator的maven依赖如下:
<</span>dependency>
<</span>groupId>com.netflix.curator</</span>groupId>
<</span>artifactId>curator-framework</</span>artifactId>
<</span>version>1.3.2</</span>version>
</</span>dependency>
下面将cursor的主要操作列出来,更多详细内容请参考:
https://github.com/Netflix/curator/wiki
实例代码如下:
public class CuratorTest {
private CuratorFramework zkTools;
public void curatorDemo() throws Exception{
zkTools = CuratorFrameworkFactory
.builder()
.connectString("127.0.0.1:2181")
.namespace("zk/test")
.retryPolicy(new RetryNTimes(5,1000))
.connectionTimeoutMs(30000)
.build();
zkTools.start();
zkTools.create()//创建一个路径
.creatingParentsIfNeeded()//如果指定的节点的父节点不存在,递归创建父节点
.withMode(CreateMode.PERSISTENT)//存储类型(临时的还是持久的)
.withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE)//访问权限
.forPath("zk/test");//创建的路径
zkTools.//对路径节点赋值
setData().
forPath("zk/test","hello world".getBytes(Charset.forName("utf-8")));
byte[] buffer = zkTools.
getData().
usingWatcher(new ZKWatch("zk/test")).forPath("zk/test");
System.out.println(new String(buffer));
}
public static void main(String[] args) throws Exception {
CuratorTest test = new CuratorTest();
test.curatorDemo();
}
public class ZKWatch implements CuratorWatcher{
private final String path;
public String getPath() {
return path;
}
public ZKWatch(String path) {
this.path = path;
}
@Override
public void process(WatchedEvent event) throws Exception {
if(event.getType() == EventType.NodeDataChanged){
byte[] data = zkTools.getData().forPath(path);
System.out.println(path+":"+new String(data,Charset.forName("utf-8")));
}
}
}
}