Zookeeper客户端Curator的使用,简单高效
Curator是Netflix公司开源的一个Zookeeper客户端,与Zookeeper提供的原生客户端相比,Curator的抽象层次更高,简化了Zookeeper客户端的开发量。
1.引入依赖:
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>4.0.0</version>
</dependency>
2。 curator 简单操作实例
public class CuratorDemo { public static void main(String[] args) throws Exception {
CuratorFramework curatorFramework = CuratorFrameworkFactory.builder() // 获取构造器
.connectString("192.168.254.135:2181," + "192.168.254.136:2181,192.168.254.137:2181") // 集群地址
.sessionTimeoutMs(4000) // session超时事件
.retryPolicy(new ExponentialBackoffRetry(1000, 3)) // 重试机制
.namespace("curator") // 命名构建 根节点
.build(); // 构造 curatorFramework.start();// 启动 连接 // 结果: /curator/mic/node1
// 原生api中,必须是逐层创建,也就是父节点必须存在,子节点才能创建
String path = curatorFramework.create() // 创建节点
.creatingParentsIfNeeded() // 如果需要创建父节点
.withMode(CreateMode.PERSISTENT) // 选择节点类型
.forPath("/wuzz/node1","1".getBytes()); // 路径及值
System.out.println(path); Stat stat = new Stat();
curatorFramework.getData() // 获取
.storingStatIn(stat).forPath("/wuzz/node1");
System.out.println(stat); curatorFramework.setData() // 修改
.withVersion(stat.getVersion()).forPath("/wuzz/node1", "xx".getBytes()); curatorFramework.delete()// 删除
.deletingChildrenIfNeeded().forPath("/mic/node1"); curatorFramework.close();// 关闭连接 }
}
监听事件实例:
public class CuratorWatcherDemo { public static void main(String[] args) throws Exception { CuratorFramework curatorFramework = CuratorFrameworkFactory.builder() // 获取构造器
.connectString("192.168.254.135:2181," +
"192.168.254.136:2181,192.168.254.137:2181") // 集群地址
.sessionTimeoutMs(4000) // session超时事件
.retryPolicy(new ExponentialBackoffRetry(1000, 3)) // 重试机制
.namespace("curator") // 命名构建 根节点
.build(); // 构造 curatorFramework.start();// 启动 连接
//当前节点的创建和删除事件监听 ---永久的
// addListenerWithNodeCache(curatorFramework,"/wuzz");
//子节点的增加、修改、删除的事件监听
addListenerWithPathChildCache(curatorFramework,"/wuzz");
//综合节点监听事件
// addListenerWithTreeCache(curatorFramework,"/wuzz");
System.in.read();
} public static void addListenerWithTreeCache(CuratorFramework curatorFramework,String path) throws Exception {
TreeCache treeCache=new TreeCache(curatorFramework,path);
TreeCacheListener treeCacheListener=new TreeCacheListener() {
@Override
public void childEvent(CuratorFramework client, TreeCacheEvent event) throws Exception {
System.out.println(event.getType()+"->"+event.getData().getPath());
}
}; treeCache.getListenable().addListener(treeCacheListener);
treeCache.start();
} /**
* PathChildCache 监听一个节点下子节点的创建、删除、更新
* NodeCache 监听一个节点的更新和创建事件
* TreeCache 综合PatchChildCache和NodeCache的特性
*/ public static void addListenerWithPathChildCache(CuratorFramework curatorFramework,String path) throws Exception {
PathChildrenCache pathChildrenCache=new PathChildrenCache(curatorFramework,path,true); PathChildrenCacheListener pathChildrenCacheListener=new PathChildrenCacheListener() {
@Override
public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception {
System.out.println("Receive Event2:"+event.getType());
}
}; pathChildrenCache.getListenable().addListener(pathChildrenCacheListener);
pathChildrenCache.start(PathChildrenCache.StartMode.NORMAL); } // 监听一个节点的更新,创建/wuzz节点事件
public static void addListenerWithNodeCache(CuratorFramework curatorFramework,String path) throws Exception {
final NodeCache nodeCache=new NodeCache(curatorFramework,path,false);
NodeCacheListener nodeCacheListener=new NodeCacheListener() {
@Override
public void nodeChanged() throws Exception {
System.out.println("Receive Event1:"+nodeCache.getCurrentData().getPath());
}
};
nodeCache.getListenable().addListener(nodeCacheListener);
nodeCache.start();
}
}
简单实用,用起来会比原生的Api会方便许多。
基于Curator的Leader选举:
Curator提供了两种选举方案:Leader Latch 和 Leader Election。下面分别介绍这两种选举方案。
Leader Latch:使用 Leader Latch 方案进行Master选举,系统将随机从候选者中选出一台作为 leader,直到调用 close() 释放leadship,此时再重新随机选举 leader,否则其他的候选者无法成为 leader。
基本原理:选择一个根路径,例如"/leader_select",多个机器同时向该根路径下创建临时顺序节点,如"/leader_latch/0002","/leader_latch/0000","/leader_latch/0001",节点编号最小(这里为0000)的zk客户端成为leader,没抢到Leader的节点都监听前一个节点的删除事件,在前一个节点删除后进行重新抢主.可以看到节点变化类似:
使用示例如下:
public class LeaderLatchTest {
private static final String zkServerIps = "192.168.1.101:2181";
private static final String masterPath = "/testZK/leader_latch"; public static void main(String[] args) {
AtomicInteger atomicInteger = new AtomicInteger();
try {//启动5个线程
for (int i = ; i < ; i++) {
new Thread(new Runnable() {
@Override
public void run() {
// 创建客户端
CuratorFramework client = getClient();
try {
client.blockUntilConnected();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(client.getState());
int number = atomicInteger.getAndIncrement();
final LeaderLatch latch = new LeaderLatch(client, masterPath, "client#" + number);
System.out.println("创建客户端:" + latch.getId());
// LeaderLatch 添加监听事件
latch.addListener(new LeaderLatchListener() {
@Override//抢主成功时触发
public void isLeader() {
System.out.println(latch.getId() + ": 我现在被选举为Leader!我开始工作了....");
try {//放弃leader。让剩下来的服务重新选主
latch.close();
} catch (IOException e) {
e.printStackTrace();
}
} @Override//不会执行
public void notLeader() {
}
});
try {
latch.start();
System.in.read();
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
System.out.println("客户端 " + latch.getId() + " 关闭");
CloseableUtils.closeQuietly(latch);
CloseableUtils.closeQuietly(client);
}
}
}).start();
}
// countDownLatch.await(); // 等待,只有所有线程都退出
} catch (Exception e) {
e.printStackTrace();
}
} private static synchronized CuratorFramework getClient() {
CuratorFramework client = CuratorFrameworkFactory.builder().connectString(zkServerIps)
.sessionTimeoutMs().connectionTimeoutMs() //.namespace("LeaderLatchTest")
.retryPolicy(new ExponentialBackoffRetry(, )).build();
client.start();
return client;
}
}
Leader Election:通过 Leader Election 选举方案进行 Master选举,需添加 LeaderSelectorListener 监听器对领导权进行控制,当节点被选为leader之后,将调用 takeLeadership 方法进行业务逻辑处理,处理完成会立即释放 leadship,重新进行Master选举,这样每个节点都有可能成为leader。autoRequeue() 方法的调用确保此实例在释放领导权后还可能获得领导权:利用Curator中InterProcessMutex分布式锁进行抢主,抢到锁的即为Leader。示例如下:
public class LeaderSelectorTest {
private static final String zkServerIps = "192.168.1.101:2181";
private static final String masterPath = "/testZK/leader_selector"; public static void main(String[] args) {
AtomicInteger atomicInteger = new AtomicInteger();
try {
for (int i = ; i < ; i++) {
new Thread(new Runnable() {
@Override
public void run() {
CuratorFramework client = getClient(); // 创建客户端
try {
client.blockUntilConnected();
} catch (InterruptedException e) {
e.printStackTrace();
}
int number = atomicInteger.getAndIncrement();
final String name = "client#" + number;
final LeaderSelector selector = new LeaderSelector(client, masterPath, new LeaderSelectorListener() {
@Override
public void takeLeadership(CuratorFramework client) throws Exception {
System.out.println(name + ": 我现在被选举为Leader!我开始工作了....");
Thread.sleep();
}
@Override
public void stateChanged(CuratorFramework curatorFramework, ConnectionState connectionState) {
}
});
System.out.println("创建客户端:" + name);
try {//在抢到leader权限并释放后,自动加入抢主队列,重新抢主
selector.autoRequeue();
selector.start();
// 阻塞
System.in.read();
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
System.out.println("客户端 " + name + " 关闭");
CloseableUtils.closeQuietly(selector);
if (!client.getState().equals(CuratorFrameworkState.STOPPED)) {
CloseableUtils.closeQuietly(client);
}
}
}
}).start();
}
} catch (Exception e) {
e.printStackTrace();
}
} private static synchronized CuratorFramework getClient() {
CuratorFramework client = CuratorFrameworkFactory.builder().connectString(zkServerIps)
.sessionTimeoutMs().connectionTimeoutMs() //.namespace("LeaderLatchTest")
.retryPolicy(new ExponentialBackoffRetry(, )).build();
client.start();
return client;
}
}
Zookeeper客户端Curator的使用,简单高效的更多相关文章
- Zookeeper客户端Curator使用详解
Zookeeper客户端Curator使用详解 前提 最近刚好用到了zookeeper,做了一个基于SpringBoot.Curator.Bootstrap写了一个可视化的Web应用: zookeep ...
- 转:Zookeeper客户端Curator使用详解
原文:https://www.jianshu.com/p/70151fc0ef5d Zookeeper客户端Curator使用详解 前提 最近刚好用到了zookeeper,做了一个基于SpringBo ...
- Zookeeper客户端Curator基本API
在使用zookeper的时候一般不使用原生的API,Curator,解决了很多Zookeeper客户端非常底层的细节开发工作,包括连接重连.反复注册Watcher和NodeExistsExceptio ...
- zookeeper(六):Zookeeper客户端Curator的API使用详解
简介 Curator是Netflix公司开源的一套zookeeper客户端框架,解决了很多Zookeeper客户端非常底层的细节开发工作,包括连接重连.反复注册Watcher和NodeExistsEx ...
- 7.5 zookeeper客户端curator的基本使用 + zkui
使用zookeeper原生API实现一些复杂的东西比较麻烦.所以,出现了两款比较好的开源客户端,对zookeeper的原生API进行了包装:zkClient和curator.后者是Netflix出版的 ...
- 聊聊、Zookeeper 客户端 Curator
[Curator] 和 ZkClient 一样,Curator 也是开源客户端,Curator 是 Netflix 公司开源的一套框架. <dependency> <groupI ...
- Zookeeper客户端 CuratorFramework使用
CuratorFramework使用 跟着实例学习ZooKeeper的用法: Curator框架应用 ZooKeeper客户端Curator使用一 创建连接
- zookeeper开源客户端curator
zookeeper的原生api相对来说比较繁琐,比如:对节点添加监听事件,当监听触发后,我们需要再次手动添加监听,否则监听只生效一次:再比如,断线重连也需要我们手动代码来判断处理等等.对于curato ...
- Zookeeper开源客户端Curator的使用
开源zk客户端-Curator 创建会话: RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000,3); CuratorFramewor ...
随机推荐
- ELK平台搭建(上)
一.目的 为指导在Centos6.8系统下搭建标准ELK平台的工作. 二.定义 Elasticsearch Logstash Kibana结合Redis协同工作. 三.适用范围 适用于运营维护组运维工 ...
- 分页插件通用处理,以asp.net mvc为例
Model: public class PaggerModel { public PaggerModel() { BarSize = ; } public PaggerModel(int total, ...
- Django REST framework 第五章 Relationships & Hyperlinked APIs
到目前为止,API内部的关系是使用主键来代表的.在这篇教程中,我们将提高API的凝聚力和可发现性,通过在相互关系上使用超链接. Creating an endpoint for the root of ...
- 经典视觉SLAM框架
经典视觉SLAM框架 整个视觉SLAM流程包括以下步骤: 1. 传感器信息读取.在视觉SLAM中主要为相机图像信息的读取和预处理. 2. 视觉里程计(Visual Odometry,VO).视觉里程计 ...
- python第l六天,lambda表达式学习,涉及filter及Map。
在python中lambda表达式可以作为匿名函数来使用,举一个简单的栗子: 以前我们写两个数相加的函数需要 #以前我们写两个数相加的函数,需要这样写 >>> def sum(x,y ...
- P4553 80人环游世界
题目地址:P4553 80人环游世界 上下界网络流 无源汇上下界可行流 给定 \(n\) 个点, \(m\) 条边的网络,求一个可行解,使得边 \((u,v)\) 的流量介于 \([B(u,v),C( ...
- log4j - 输出格式控制, PatternLayout参数含义以及详细配置
转载自:https://blog.csdn.net/reserved_person/article/details/52849505 做项目被log4j的输出格式化参数搞烦了,索性把API的相关部分大 ...
- xv6 + Qemu 在Ubuntu下编译运行教程【转】
转自:https://blog.csdn.net/yinglang19941010/article/details/49310111 如果想要离线看教程,可以下载该 文档 一.使用工具说明 1. ...
- Liunx系统命令sed的使用
作者:邓聪聪 Liunx命令中sed的使用历程 sed [-nefr] [动作]选项与参数:-n :使用安静(silent)模式.在一般 sed 的用法中,所有来自 STDIN 的数据一般都会被列出 ...
- UrlDecode
void Decode(char *p){int i=0;while(*(p+i)){ if ((*p=*(p+i)) == '%') { *p=*(p+i+1) >= 'A' ? ((*(p+ ...