1.什么是zookeeper
zookeeker 是什么 他是一个分布式协调,服务治理,服务注册的一个开源框架 中文名字叫做动物管理员(ps:据说原因是当年各种框架流行使用动物来命名,员工们开玩笑的把它称为动物管理员这不开不知道这一开还真的就用了- -)
2.zookeeper的存储格式
zookeeper可以理解为map属性存储结构 每个节点被称为ZNode 类似于文件夹式结构,关于ZNode zookeeper可是做了不少手脚无论是有序节点(-s) 还是 临时节点(-e) 这些都服务与zookeeper 为zookeeper添加了不少的灵活度
3.zookeeper原生操作
最开始时候我也在使用zk的原生 也就是如下
/** zookeeper地址 */
static final String CONNECT_ADDR = "192.168.80.88:2181,192.168.80.87:2181,192.168.80.86:2181";
/** session超时时间 */
static final int SESSION_OUTTIME = 2000;//ms
/** 信号量,阻塞程序执行,用于等待zookeeper连接成功,发送成功信号 */
static final CountDownLatch connectedSemaphore = new CountDownLatch(1);
public static void main(String[] args) throws Exception{
ZooKeeper zk = new ZooKeeper(CONNECT_ADDR, SESSION_OUTTIME, new Watcher(){
@Override
public void process(WatchedEvent event) {
//获取事件的状态
KeeperState keeperState = event.getState();
EventType eventType = event.getType();
//如果是建立连接
if(KeeperState.SyncConnected == keeperState){
if(EventType.None == eventType){
//如果建立连接成功,则发送信号量,让后续阻塞程序向下执行
connectedSemaphore.countDown();
System.out.println("zk 建立连接");
}
}
}
});
//进行阻塞
connectedSemaphore.await();
System.out.println("..");
//创建父节点
// zk.create("/testRoot", "testRoot".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
//创建子节点,使用EPHEMERAL,主程序执行完成后该节点被删除,只在本次会话内有效,可以用作分布式锁。
// zk.create("/testRoot/children", "children data".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
//获取节点信息
// byte[] data = zk.getData("/testRoot", false, null);
// System.out.println(new String(data));
// System.out.println(zk.getChildren("/testRoot", false));
//修改节点的值,-1表示跳过版本检查,其他正数表示如果传入的版本号与当前版本号不一致,则修改不成功,删除是同样的道理。
// zk.setData("/testRoot", "modify data root".getBytes(), -1);
// byte[] data = zk.getData("/testRoot", false, null);
// System.out.println(new String(data));
//判断节点是否存在
// System.out.println(zk.exists("/testRoot/children", false));
//删除节点
// zk.delete("/testRoot/children", -1);
// System.out.println(zk.exists("/testRoot/children", false));
zk.close();
可以看出来 zk原生是十分笨拙的 为什么这么说的原因如下:
1 .不支持递归操作 zk原生不允许创建持久化节点时候递归创建
2.zk建立连接时需要等待建立成功才可以使用否则就抛出异常了 这里也是为什么使用countdown
3.zk watch 机制是单方面的 一次性的使用完毕就销毁
4.相较于curator 语法表达不明确.
4.那么吹了这么久curator 他到底是什么呢?
直接上代码:
static CountDownLatch countDownLatch = new CountDownLatch(1);
public static void main(String[] args) throws Exception {
//虽然这里这么写但是是为了联系countdown 其实curator 本身就是可以
Callable<CuratorFramework> curatorFrameworkCallable = new Callable<CuratorFramework>() {
@Override
public CuratorFramework call() throws Exception {
CuratorFramework curatorFramework1 = CuratorFrameworkFactory.
newClient("0.0.0.0:2181", new RetryNTimes(10, 5000));
curatorFramework1.start();
while (true) {
if ("STARTED".equals(curatorFramework1.getState().name())) {
countDownLatch.countDown();
return curatorFramework1;
}
}
}
};
//这里也可以直接调用call 但是这样是阻塞 必须县城返回了 才能获取 这里使用了 线程池 技术 用Future去接异步返回
ExecutorService executor = Executors.newCachedThreadPool();
Future<CuratorFramework> curatorFrameworkFuture = executor.submit(curatorFrameworkCallable);
//这个Get 才是真正的运行
CuratorFramework curatorFramework = curatorFrameworkFuture.get();
//这里也用到了countDown java 的current下的工具类 还有cycleBarrier 区别瞬发还是队列排序发
countDownLatch.await();
System.out.println("链接成功");
//开始操作zk;
//withmode 模式 -e 临时 -s 有序 crud 就这些 然后还有if XXX 那个方法 就是如果级联操作可选
// curatorFramework.create().withProtection().withMode(CreateMode.EPHEMERAL).forPath("/hellor","hjelliora".getBytes());
//我比较重视watch
// Path Cache:监视一个路径下1)孩子结点的创建、2)删除,3)以及结点数据的更新。产生的事件会传递给注册的PathChildrenCacheListener。
// Node Cache:监视一个结点的创建、更新、删除,并将结点的数据缓存在本地。
// Tree Cache:Path Cache和Node Cache的“合体”,监视路径下的创建、更新、删除事件,并缓存路径下所有孩子结点的数据。
其实这里可以不使用countdown 因为curator这里会等待zookeeper建立成功连接之后才最继续 也就是说他帮你实现了countdown
也可以不用使用Callble我这里是练习将多个技术串联起来方便回顾.
从上面我们可以看出来 这里使用了flume链式语法构建语义清楚这里我只做了一个用来象征其余操作都差不多
其次这里的watch可以实现循环监听
好了这篇文章就到这里来需求了!