一.curator简介
curator是Netflix公司开源的一个zookeeper客户端,后捐献给apache,curator框架在zookeeper原生API接口上进行了包装,解决了很多zookeeper客户端非常底层的细节开发。提供zookeeper各种应用场景(比如:分布式锁服务、集群领导选举、共享计数器、缓存机制、分布式队列等)的抽象封装,实现了Fluent风格的API接口,是最好用、最流行的zookeeper的客户端。
二.原生zookeeperAPI的不足
- 连接对象异步创建,需要开发人员自行编码等待。
- 连接没有自动重连超时机制。
- watcher一次注册生效一次。
- 不支持递归创建树形节点。
三.curator的特点
- 解决session会话超时重连。
- watcher反复注册。
- 简化开发api。
- 遵循Fluent风格的API。
- 提供了分布式锁服务、共享计数器、缓存机制等机制。
四.curator连接zookeeper服务器
1.代码块
package com.fengmo;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.RetryOneTime;
//测试用curator连接zookeeper集群
public class CuratorConnection {
public static void main(String[] args) {
//创建连接对象
CuratorFramework client = CuratorFrameworkFactory.builder()
//IP地址端口号,多个zookeeper服务器用逗号分隔
.connectString("192.168.83.138:2181,192.168.83.138:2182,192.168.83.138:2183")
//会话超时时间
.connectionTimeoutMs(5000)
//重连机制:当会话超时之后重连机制
.retryPolicy(new RetryOneTime(3000))
//命名空间
.namespace("create")
//构建对象
.build();
//打开连接
client.start();
System.out.println("判断连接是否成功:" + client.isStarted());//true成功,false失败
//关闭连接
client.close();
System.out.println("连接关闭");
}
}
2.范例
五.curator重连机制
1.代码块
package com.fengmo;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.curator.retry.RetryNTimes;
import org.apache.curator.retry.RetryOneTime;
import org.apache.curator.retry.RetryUntilElapsed;
import org.junit.Test;
//curator重连机制
public class CuratorConnection2 {
@Test
/*
3秒后重连一次,只重连一次
new RetryOneTime(3000)
*/
public void test1(){
//创建连接对象
CuratorFramework client = CuratorFrameworkFactory.builder()
//IP地址端口号,多个zookeeper服务器用逗号分隔
.connectString("192.168.83.138:2181,192.168.83.138:2182,192.168.83.138:2183")
//会话超时时间
.connectionTimeoutMs(5000)
//重连机制:当会话超时之后重连机制
.retryPolicy(new RetryOneTime(3000))
//命名空间
.namespace("create")
//构建对象
.build();
//打开连接
client.start();
System.out.println("判断连接是否成功:" + client.isStarted());//true成功,false失败
//关闭连接
client.close();
System.out.println("连接关闭");
}
@Test
/*
3秒后重连一次,重连3次。参数一:重连次数,参数二:重连时间
new RetryNTimes(3,3000)
*/
public void test2(){
//创建连接对象
CuratorFramework client = CuratorFrameworkFactory.builder()
//IP地址端口号,多个zookeeper服务器用逗号分隔
.connectString("192.168.83.138:2181,192.168.83.138:2182,192.168.83.138:2183")
//会话超时时间
.connectionTimeoutMs(5000)
//重连机制:当会话超时之后重连机制
.retryPolicy(new RetryNTimes(3,3000))
//命名空间
.namespace("create")
//构建对象
.build();
//打开连接
client.start();
System.out.println("判断连接是否成功:" + client.isStarted());//true成功,false失败
//关闭连接
client.close();
System.out.println("连接关闭");
}
@Test
/*
每3秒重连一次,总等待时间超过10秒后停止重连。参数一:总等待时间,参数二:重连时间。
new RetryUntilElapsed(10000,3000)
*/
public void test3(){
//创建连接对象
CuratorFramework client = CuratorFrameworkFactory.builder()
//IP地址端口号,多个zookeeper服务器用逗号分隔
.connectString("192.168.83.138:2181,192.168.83.138:2182,192.168.83.138:2183")
//会话超时时间
.connectionTimeoutMs(5000)
//重连机制:当会话超时之后重连机制
.retryPolicy(new RetryUntilElapsed(10000,3000))
//命名空间
.namespace("create")
//构建对象
.build();
//打开连接
client.start();
System.out.println("判断连接是否成功:" + client.isStarted());//true成功,false失败
//关闭连接
client.close();
System.out.println("连接关闭");
}
@Test
/*
重连间隔会随着重连次数的增加而增加
baseSleepTimeMs * Math.max(1,random.nextInt(1 << (retryCount + 1)))
*/
public void test4(){
//创建连接对象
CuratorFramework client = CuratorFrameworkFactory.builder()
//IP地址端口号,多个zookeeper服务器用逗号分隔
.connectString("192.168.83.138:2181,192.168.83.138:2182,192.168.83.138:2183")
//会话超时时间
.connectionTimeoutMs(5000)
//重连机制:当会话超时之后重连机制
.retryPolicy(new ExponentialBackoffRetry(1000,3))
//命名空间
.namespace("create")
//构建对象
.build();
//打开连接
client.start();
System.out.println("判断连接是否成功:" + client.isStarted());//true成功,false失败
//关闭连接
client.close();
System.out.println("连接关闭");
}
}
2.范例一【重连一次】
3.范例二【设置重连几次和设置重连时间】
4.范例三【设置总等待时间和重连时间】
5.范例四【重连间隔会随着重连次数的增加而增加】
六.curator的创建节点
1.代码块
package com.fengmo;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.BackgroundCallback;
import org.apache.curator.framework.api.CuratorEvent;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.curator.retry.RetryOneTime;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.data.ACL;
import org.apache.zookeeper.data.Id;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
//测试用curator创建节点
public class CuratorCreateNode {
String IP = "192.168.83.138:2181,192.168.83.138:2182,192.168.83.138:2183";
CuratorFramework client;
@Before
public void before(){
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000,3);
client = CuratorFrameworkFactory.builder()
.connectString(IP)
.sessionTimeoutMs(5000)
.retryPolicy(retryPolicy)
.namespace("create")
.build();
client.start();
}
@After
public void after(){
client.close();
}
@Test
public void create1()throws Exception{
//新增节点
client.create()
//节点类型
.withMode(CreateMode.PERSISTENT)
//节点的权限列表
.withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE)
//参数一:节点路径,参数二:节点数据
.forPath("/node1","node1".getBytes());
System.out.println("结束");
}
@Test
public void create2()throws Exception{
//自定义权限列表
//权限列表
List<ACL> list = new ArrayList<ACL>();
//授权模式和授权对象
Id id = new Id("ip","192.168.83.1");
list.add(new ACL(ZooDefs.Perms.ALL,id));
client.create().withMode(CreateMode.PERSISTENT).withACL(list).forPath("/node2","bbbbb".getBytes());
System.out.println("结束");
}
@Test
public void create3()throws Exception{
//递归创建节点树
client.create()
//creatingParentsIfNeeded方法当父节点不存在,则直接创建父节点。递归创建
.creatingParentsIfNeeded()
//节点类型
.withMode(CreateMode.PERSISTENT)
//权限
.withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE)
//节点路径和节点内容
.forPath("/node3/node31","node31".getBytes());
System.out.println("结束");
}
@Test
public void create4()throws Exception{
//异步方式创建节点
client.create()
//creatingParentsIfNeeded方法当父节点不存在,则直接创建父节点。递归创建
.creatingParentsIfNeeded()
//节点类型
.withMode(CreateMode.PERSISTENT)
//权限
.withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE)
//开启异步回调接口
.inBackground(new BackgroundCallback() {
@Override
public void processResult(CuratorFramework curatorFramework, CuratorEvent curatorEvent) throws Exception {
//curatorFramework连接对象,curatorEvent是事件对象
System.out.println(curatorEvent.getPath()); //当前节点的路径
System.out.println(curatorEvent.getType()); //当前节点的事件类型
}
})
//节点路径和节点内容
.forPath("/node4","node4".getBytes());
Thread.sleep(5000);
System.out.println("结束");
}
}
2.范例一【新增节点】
3.范例二【设置自定义权限创建节点】
4.范例三【递归创建节点(创建多层节点)】
5.范例四【异步创建节点】
七.curator的更新节点
1.代码块
package com.fengmo;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.BackgroundCallback;
import org.apache.curator.framework.api.CuratorEvent;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.data.ACL;
import org.apache.zookeeper.data.Id;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
//测试用curator更新节点
public class CuratorUpdateNode {
String IP = "192.168.83.138:2181,192.168.83.138:2182,192.168.83.138:2183";
CuratorFramework client;
@Before
public void before(){
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000,3);
client = CuratorFrameworkFactory.builder()
.connectString(IP)
.sessionTimeoutMs(5000)
.retryPolicy(retryPolicy)
.namespace("set")
.build();
client.start();
}
@After
public void after(){
client.close();
}
@Test
public void update1()throws Exception{
//更新节点
client.setData()
//参数一:节点路径,参数二:修改后的节点数据
.forPath("/node1","node11".getBytes());
System.out.println("结束");
}
@Test
public void update2()throws Exception{
//根据版本号更新节点
client.setData()
//大于0的数是设置当前版本号,-1为版本号不参与。注意:当前版本号输入错误,则修改失败
.withVersion(-1)
//参数一:节点路径,参数二:修改后的节点数据
.forPath("/node1","node22222".getBytes());
System.out.println("结束");
}
@Test
public void update3()throws Exception{
//异步操作更新节点
client.setData()
//大于0的数是设置当前版本号,-1为版本号不参与。注意:当前版本号输入错误,则修改失败
.withVersion(-1)
//开启异步访问
.inBackground(new BackgroundCallback() {
@Override
public void processResult(CuratorFramework curatorFramework, CuratorEvent curatorEvent) throws Exception {
//curatorFramework连接对象,curatorEvent是事件对象
System.out.println(curatorEvent.getPath()); //当前节点的路径
System.out.println(curatorEvent.getType()); //当前节点的事件类型
}
})
//参数一:节点路径,参数二:修改后的节点数据
.forPath("/node1","node3333".getBytes());
Thread.sleep(5000);
System.out.println("结束");
}
}
2.范例一【更新节点】
3.范例二【根据版本号更新节点】
4.范例三【异步操作更新节点】
八.curator的删除节点
1.代码块
package com.fengmo;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.BackgroundCallback;
import org.apache.curator.framework.api.CuratorEvent;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
//测试用curator删除节点
public class CuratorDeleteNode {
String IP = "192.168.83.138:2181,192.168.83.138:2182,192.168.83.138:2183";
CuratorFramework client;
@Before
public void before(){
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000,3);
client = CuratorFrameworkFactory.builder()
.connectString(IP)
.sessionTimeoutMs(5000)
.retryPolicy(retryPolicy)
.namespace("delete")
.build();
client.start();
}
@After
public void after(){
client.close();
}
@Test
public void delete1()throws Exception{
//删除节点
client.delete()
//参数:节点路径
.forPath("/node1");
System.out.println("结束");
}
@Test
public void delete2()throws Exception{
//删除节点
client.delete()
//大于0的数是设置当前版本号,-1为版本号不参与。注意:当前版本号输入错误,则修改失败
.withVersion(-1)
//参数:节点路径
.forPath("/node1");
System.out.println("结束");
}
@Test
public void delete3()throws Exception{
//删除包含子节点的节点
client.delete()
//设置如果存在子节点,则一起删除
.deletingChildrenIfNeeded()
//大于0的数是设置当前版本号,-1为版本号不参与。注意:当前版本号输入错误,则删除失败
.withVersion(4)
//参数:节点路径
.forPath("/node1");
System.out.println("结束");
}
@Test
public void delete4()throws Exception{
//异步方式删除节点
client.delete()
//设置如果存在子节点,则一起删除
.deletingChildrenIfNeeded()
//大于0的数是设置当前版本号,-1为版本号不参与。注意:当前版本号输入错误,则删除失败
.withVersion(4)
//异步请求方式
.inBackground(new BackgroundCallback() {
@Override
public void processResult(CuratorFramework curatorFramework, CuratorEvent curatorEvent) throws Exception {
//curatorFramework连接对象,curatorEvent是事件对象
System.out.println(curatorEvent.getPath()); //当前节点的路径
System.out.println(curatorEvent.getType()); //当前节点的事件类型
}
})
//参数:节点路径
.forPath("/node1");
Thread.sleep(5000);
System.out.println("结束");
}
}
2.范例一【删除节点】
3.范例二【根据版本号删除节点】
4.范例三【异步操作删除节点】
九.curator的查询节点
1.代码块
package com.fengmo;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.BackgroundCallback;
import org.apache.curator.framework.api.CuratorEvent;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.data.Stat;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
//测试用curator获取节点
public class CuratorGetNode {
String IP = "192.168.83.138:2181,192.168.83.138:2182,192.168.83.138:2183";
CuratorFramework client;
@Before
public void before(){
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000,3);
client = CuratorFrameworkFactory.builder()
.connectString(IP)
.sessionTimeoutMs(5000)
.retryPolicy(retryPolicy)
.namespace("get")
.build();
client.start();
}
@After
public void after(){
client.close();
}
@Test
public void get1()throws Exception{
//读取节点数据
byte[] bys = client.getData().forPath("/node1");//参数是节点路径
System.out.println("节点数据是" + new String(bys));
}
@Test
public void get2()throws Exception{
//读取节点数据时读取节点的属性
Stat stat = new Stat();
byte[] bys = client.getData()
//读取属性
.storingStatIn(stat)
.forPath("/node1");//参数是节点路径
System.out.println("节点数据是" + new String(bys));
System.out.println("节点的版本号是" + stat.getVersion());
}
@Test
public void get3()throws Exception{
//异步方式读取节点的数据
client.getData()
.inBackground(new BackgroundCallback() {
@Override
public void processResult(CuratorFramework curatorFramework, CuratorEvent curatorEvent) throws Exception {
//节点的路径
System.out.println(curatorEvent.getPath());
//事件类型
System.out.println(curatorEvent.getType());
//节点数据
System.out.println(new String(curatorEvent.getData()));
}
})
.forPath("/node1");
Thread.sleep(5000);
System.out.println("结束");
}
}
2.范例一【查询节点】
3.范例二【读取节点数据时读取节点属性】
4.范例三【异步请求获取节点数据】
十.curator的查询子节点
1.代码块
package com.fengmo;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.BackgroundCallback;
import org.apache.curator.framework.api.CuratorEvent;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.data.Stat;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.util.List;
//测试用curator获取子节点
public class CuratorGetChildNode {
String IP = "192.168.83.138:2181,192.168.83.138:2182,192.168.83.138:2183";
CuratorFramework client;
@Before
public void before(){
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000,3);
client = CuratorFrameworkFactory.builder()
.connectString(IP)
.sessionTimeoutMs(5000)
.retryPolicy(retryPolicy)
.namespace("get")
.build();
client.start();
}
@After
public void after(){
client.close();
}
@Test
public void get1()throws Exception{
//读取所有子节点数据
List<String> list = client.getChildren().forPath("/node2");//参数是节点路径
for(String s : list){
System.out.println(s); //节点数据
}
}
@Test
public void get2()throws Exception{
//异步方式获取所有子节点数据
client.getChildren()
.inBackground(new BackgroundCallback() {
@Override
public void processResult(CuratorFramework curatorFramework, CuratorEvent curatorEvent) throws Exception {
//节点的路径
System.out.println(curatorEvent.getPath());
//事件类型
System.out.println(curatorEvent.getType());
//节点的所有子节点
List<String> list = curatorEvent.getChildren();
for(String s : list){
System.out.println("子节点数据是" + s);
}
}
})
.forPath("/node2");
Thread.sleep(5000);
System.out.println("结束");
}
}
2.范例一【查询子节点】
3.范例二【异步请求查询子节点】
十一.curator的判断节点是否存在
1.代码块
package com.fengmo;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.BackgroundCallback;
import org.apache.curator.framework.api.CuratorEvent;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.data.Stat;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.util.List;
//测试用curator查询节点是否存在
public class CuratorExist {
String IP = "192.168.83.138:2181,192.168.83.138:2182,192.168.83.138:2183";
CuratorFramework client;
@Before
public void before(){
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000,3);
client = CuratorFrameworkFactory.builder()
.connectString(IP)
.sessionTimeoutMs(5000)
.retryPolicy(retryPolicy)
.namespace("get")
.build();
client.start();
}
@After
public void after(){
client.close();
}
@Test
public void exist1()throws Exception{
//判断节点是否存在
Stat stat = client.checkExists()
//节点路径
.forPath("/node2");
System.out.println("获取版本号:" + stat.getVersion());
}
@Test
public void exist2()throws Exception{
//异步方式判断节点是否存在
client.checkExists()
.inBackground(new BackgroundCallback() {
@Override
public void processResult(CuratorFramework curatorFramework, CuratorEvent curatorEvent) throws Exception {
//节点路径
System.out.println(curatorEvent.getPath());
//事件类型
System.out.println(curatorEvent.getType());
//获取节点的版本号
System.out.println(curatorEvent.getStat().getVersion());
}
})
.forPath("/node2");
Thread.sleep(5000);
System.out.println("结束");
}
}
2.范例一【判断该节点是否存在】
3.范例二【异步请求该节点是否存在】
十二.curator的事件监听事件
1.说明
curator提供了俩种Watcher(Cache)来监听结点的变化。
- Node Cache:只是监听某一个特点的节点,监听节点的新增和修改。
- PathChildren Cache:监控一个ZNode的子节点,当一个子节点增加、更新、删除时,Path Cache会改变它的状态,会包含最新的子节点,子节点的数据和状态。
2.代码块
package com.fengmo;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.cache.*;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
//测试curator事件监听机制
public class CuratorWatcher {
String IP = "192.168.83.138:2181,192.168.83.138:2182,192.168.83.138:2183";
CuratorFramework client;
@Before
public void before(){
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000,3);
client = CuratorFrameworkFactory.builder()
.connectString(IP)
.sessionTimeoutMs(5000)
.retryPolicy(retryPolicy)
.namespace("watcher")
.build();
client.start();
}
@After
public void after(){
client.close();
}
@Test
//注意事项:重复监听事件
public void watcher1() throws Exception {
//监视某个节点的数据变化
//参数1:连接对象。参数2:监视的节点路径。
final NodeCache nodeCache = new NodeCache(client,"/watcher1"); //内部类使用需要用final修饰
//启动监视器对象
nodeCache.start();
nodeCache.getListenable().addListener(new NodeCacheListener() {
@Override
//节点变化回调的方法
public void nodeChanged() throws Exception {
//获取节点路径
System.out.println(nodeCache.getCurrentData().getPath());
//获取节点数据
System.out.println(new String(nodeCache.getCurrentData().getData()));
//获取节点的版本号
System.out.println(nodeCache.getCurrentData().getStat().getVersion());
}
});
Thread.sleep(30000);
System.out.println("结束");
//关闭监视器对象
nodeCache.close();
}
@Test
//监视子节点的变化
public void watcher2() throws Exception {
//参数一:连接对象。参数二:监视的节点路径。参数三:事件中是否可以获取节点的数据
PathChildrenCache pathChildrenCache = new PathChildrenCache(client,"/watcher1",true);
//启动监听
pathChildrenCache.start();
pathChildrenCache.getListenable().addListener(new PathChildrenCacheListener() {
@Override
//当子节点方法变化时回调的方法
public void childEvent(CuratorFramework curatorFramework, PathChildrenCacheEvent pathChildrenCacheEvent) throws Exception {
//节点的事件类型
System.out.println(pathChildrenCacheEvent.getType());
//节点的路径
System.out.println(pathChildrenCacheEvent.getData().getPath());
//节点数据
System.out.println(pathChildrenCacheEvent.getData().getData());
}
});
Thread.sleep(100000);
System.out.println("结束");
pathChildrenCache.close();
}
}
3.范例一【当前节点的事件监听】
4.范例二【当前节点的子节点事件监听】
十三.curator的事务
1.代码块
package com.fengmo;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.BackgroundCallback;
import org.apache.curator.framework.api.CuratorEvent;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.data.Stat;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
//测试用curator的事务
public class CuratorTransaction {
String IP = "192.168.83.138:2181,192.168.83.138:2182,192.168.83.138:2183";
CuratorFramework client;
@Before
public void before(){
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000,3);
client = CuratorFrameworkFactory.builder()
.connectString(IP)
.sessionTimeoutMs(5000)
.retryPolicy(retryPolicy)
.namespace("tra")
.build();
client.start();
}
@After
public void after(){
client.close();
}
@Test
public void tra1()throws Exception{
/*
事务开启:
当出现异常时,只要没走到commit方法,则会事务回滚。
当没有异常时,走到commit方法,则事务提交。
*/
client.inTransaction() //开启事务:inTransaction
.create() //创建节点
.forPath("/node1","node1".getBytes()) //节点路径和节点数据
.and()
.setData().forPath("/node2","aaaa".getBytes()) //setData修改数据,forPath节点路径和节点数据
.and()
.commit(); //事务提交:commit
}
}
2.范例
十四.curator的分布式锁
1.说明
curator的分布式锁分为
InterProcessMutex:分布式可重入排他锁。
InterProcessReadWriteLock:分布式读写锁。
2.代码块
package com.fengmo;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.locks.InterProcessLock;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.apache.curator.framework.recipes.locks.InterProcessReadWriteLock;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class CuratorLock {
String IP = "192.168.83.138:2181,192.168.83.138:2182,192.168.83.138:2183";
CuratorFramework client;
@Before
public void before(){
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000,3);
client = CuratorFrameworkFactory.builder()
.connectString(IP)
.sessionTimeoutMs(5000)
.retryPolicy(retryPolicy)
.namespace("get")
.build();
client.start();
}
@After
public void after(){
client.close();
}
@Test
//顺序:先进后出
public void lock1() throws Exception {
//排他锁
//参数一:连接对象。参数二:节点路径
InterProcessLock interProcessLock = new InterProcessMutex(client,"/lock1");
System.out.println("等待获取锁对象!");
//获取锁
interProcessLock.acquire();
for (int i = 1;i <= 10;i++){
Thread.sleep(3000);
System.out.println(i);
}
//释放锁
interProcessLock.release();
System.out.println("等待释放锁!");
}
@Test
//顺序:先进先出
public void lock2() throws Exception {
//读写锁
InterProcessReadWriteLock interProcessReadWriteLock = new InterProcessReadWriteLock(client,"/lock1");
//获取读锁对象
InterProcessLock interProcessLock = interProcessReadWriteLock.readLock();
System.out.println("等待获取锁对象!");
//获取锁
interProcessLock.acquire();
for(int i = 1;i <= 10;i++){
Thread.sleep(3000);
System.out.println(i);
}
//释放锁
interProcessLock.release();
System.out.println("等待释放锁!");
}
@Test
//顺序:先进先出
public void lock3() throws Exception {
//读写锁
InterProcessReadWriteLock interProcessReadWriteLock = new InterProcessReadWriteLock(client,"/lock1");
//获取写锁对象
InterProcessLock interProcessLock = interProcessReadWriteLock.writeLock();
System.out.println("等待获取锁对象!");
//获取锁
interProcessLock.acquire();
for(int i = 1;i <= 10;i++){
Thread.sleep(3000);
System.out.println(i);
}
//释放锁
interProcessLock.release();
System.out.println("等待释放锁!");
}
}
3.范例一【排他锁,顺序先进后出】
4.范例二【读写锁,顺序先进先出】
(1)读取锁
(2)写入锁
十五.zookeeper的监控指令
1.说明
zookeeper支持某些特定的四字命令与其的交互。它们大多是查询命令,用来获取zookeeper服务的当前状态及相关信息。用户在客户端可以通过telnet或nc向zookeeper提交相应的命令。zookeeper常用四字命令见下表所示:
命令 | 描述 |
---|---|
conf | 输出相关服务配置的详细信息。比如端口、zk数据及日志配置路径、最大连接数,session超时时间、serverId等 |
cons | 列出所有连接到这台服务器的客户端连接/会话的详细信息。包括"接受/发送"的包数量、session id、操作延迟、最后的操作执行等信息 |
crst | 重置当前这台服务器所有连接/会话的统计信息 |
dump | 列出未经处理的会话和临时节点 |
envi | 输出关于服务器的环境详细信息 |
ruok | 测试服务是否处于正确运行状态。 |
stat | 输出服务器的详细信息:接收/发送包数量、连接数、模式(leader/follower)、节点总数、延迟。所有客户端的列表。 |
srst | 重置server状态 |
wchs | 列出服务器watches的简洁信息:连接总数、watching节点总数和watches总数 |
wchc | 通过session分组,列出watch的所有节点,它的输出是一个与watch相关的会话的节点列表 |
mntr | 列出集群的健康状态。包括"接受/发送"的包数量、操作延迟、当前服务模式(leader/follower)、节点总数、watch总数、临时节点总数 |
2.nc命令工具安装
#root用户安装
#下载安装包
wget http://vault.centos.org/6.6/os/x86_64/Packages/nc-1.84-22.el6.x85_64.rpm
#rpm安装
rpm -iUv nc-1.84-22.e16.x86_64.rpm
#第二种安装
yum install -y nc
使用方式,在shell终端输入:echo mntr | nc localhost 2181
3.nc命令的使用
(1)语法
echo nc指令 | nc ip地址 端口号
(2)演示
4.conf指令
(1)说明
conf:输出相关服务配置的详细信息。
(2)语法
# shell终端输入
echo conf | nc ip地址 端口号
(3)范例
(4)配置说明
属性 | 含义 |
---|---|
clientPort | 客户端端口号 |
dataDir | 数据快照文件目录默认情况下100000次事务操作生成一次快照 |
dataLogDir | 事务日志文件目录,生产环境中放在独立的磁盘上 |
tickTime | 服务器之间或客户端与服务器之间维持心跳的时间间隔(以毫秒为单位) |
minSessionTimeout | 最小session超时minSessionTimeout=tickTime*2 最小超时时间是2s |
maxSessionTimeout | 最大session超时maxSessionTimeout=tickTime*20 最大超时时间是40s |
serverId | 服务器编号 |
initLimit | 集群中的follower服务器(F)与leader服务器(L)之间初始连接时能容忍的最多心跳数 |
syncLimit | 集群中的follower服务器(F)与leader服务器(L)之间请求和应答之间能容忍的最多心跳数 |
electionAlg | 0.基于UDP的LeaderElection 1.基于UPD的FastLeaderElection 2.基于UDP和认证的FastLeaderElection 3.基于TCP的FastLeaderElection 在3.4.10版本中,默认值为3。另外三种算法已经被弃用,并且有计划在之后的版本中将它们彻底删除而不再支持。 |
electionPort | 选举端口 |
quorumPort | 数据通信端口 |
peerType | 是否为观察者。1为观察者 |
5.cons指令
(1)说明
cons:列出所有连接到这台服务器的客户端连接/会话的详细信息。
(2)语法
#shell终端输入
echo cons | nc ip地址 端口号
(3)范例
(4)配置说明
属性 | 含义 |
---|---|
ip | ip地址 |
port | 端口号 |
queued | 等待被处理的请求书,请求缓存在队列中 |
received | 收到的包数 |
sent | 发送的包数 |
sid | 会话id |
lop | 最后的操作: GETD-读取数据 DELE-删除数据 CREA-创建数据 |
est | 连接时间戳 |
to | 超时时间 |
lcxid | 当前会话的操作id |
lzxid | 最大事务id |
lresp | 最后响应时间戳 |
llat | 最后/最新的延时 |
minlat | 最小延时 |
maxlat | 最大延时 |
avglat | 平均延时 |
6.crst指令
(1)说明
crst:重置当前这台服务器所有连接/会话的统计信息
(2)语法
#shell终端输入
echo crst | nc ip地址 端口号
(3)范例
7.dump命令
(1)说明
dump:列出未经处理的会话和临时节点。
(2)语法
#在shell终端输入
echo dump | nc ip地址 端口号
(3)范例
8.envi指令
(1)说明
envi:输出关于服务器的环境配置信息。
(2)语法
#shell终端输入
echo envi | nc ip地址 端口号
(3)范例
(4)配置说明
属性 | 含义 |
---|---|
zookeeper.version | 版本 |
host.name | host信息 |
java.version | java版本 |
jva.vendor | 供应商 |
java.home | 运行环境所在目录 |
java.class.path | classpath |
java.library.path | 第三方库指定非java类包的位置(如:dll,so) |
java.io.tmpdir | 默认的临时文件路径 |
java.compiler | JIT编译器的名称 |
os.name | LInux |
os.arch | amd64 |
os.version | 3.10.0-514.el7.x86_64 |
user.name | zookeeper【用户名】 |
user.home | /home/zookeeper【用户所在路径】 |
user.dir | /home/zookeeper/zookeeper2181/bin 【客户端的所在路径】 |
9.ruok指令
(1)说明
ruok:测试服务是否处于正确运行状态。
(2)语法
# shell终端输入
echo ruok | nc ip地址 端口号
(3)范例
10.stat指令
(1)说明
stat:输出服务器的详细信息与srvr相似,但是多了每个链接的会话信息。
(2)语法
# shell终端输入
echo stat | nc ip地址 端口号
(3)范例
(4)配置说明
属性 | 含义 |
---|---|
Zookeeper version | 版本 |
Latency min/avg/max | 延时 |
Received | 收包 |
Sent | 发包 |
Connections | 连接数 |
Outstanding | 堆积数 |
Zxid | 最大事物id |
Mode | 服务器角色 |
Node count | 节点数 |
11.srst指令
(1)说明
srst:重置server状态。
(2)语法
# shell终端输入
echo srst | nc ip地址 端口号
(3)范例
12.wchs指令
(1)说明
wchs:列出服务器watches的简洁信息
(2)语法
# shell终端输入
echo wchs | nc ip地址 端口号
(3)范例
(4)配置说明
属性 | 含义 |
---|---|
connectsions | 连接数 |
watch-paths | watch节点数 |
watchers | watcher数量 |
13.wchc指令
(1)说明
wchc:通过session分组,列出watch的所有节点,它的输出是一个与watch相关的会话的节点列表。
(2)遇见的相关问题和解决方案
(2-1)代码块
# 问题
wchc is not executed because it is not in the whitelist。
# 解决方案
# 修改启动指令 zkServer.sh
# 注意找到这个信息
else
echo "JMX disabled by user request" >&2
ZOOMAIN="org.apache.zookeeper.server.quorum.QuorumPeerMain"
fi
# 下面添加如下信息
ZOOMAIN="-Dzookeeper.4lw.commands.whitelist=* ${ZOOMAIN}"
(2-2)范例
(3)语法
# shell终端输入
echo wchc | nc ip地址 端口号
(4)范例
14.wchp指令
(1)说明
wchp:通过路径分组,列出所有的watch的session id信息。
(2)遇见的相关问题和解决方案
(2-1)代码块
# 问题
wchp is not executed because it is not in the whitelist。
# 解决方案
# 修改启动指令 zkServer.sh
# 注意找到这个信息
else
echo "JMX disabled by user request" >&2
ZOOMAIN="org.apache.zookeeper.server.quorum.QuorumPeerMain"
fi
# 下面添加如下信息
ZOOMAIN="-Dzookeeper.4lw.commands.whitelist=* ${ZOOMAIN}"
(2-2)范例
(3)语法
# shell终端输入
echo wchp | nc ip地址 端口号
(4)范例
15.mntr指令
(1)说明
mntr:列出服务器的健康状态。
(2)语法
echo mntr | nc ip地址 端口号
(3)范例
(4)配置说明
属性 | 含义 |
---|---|
zk_version | 版本 |
zk_avg_latency | 平均延时 |
zk_max_latency | 最大延时 |
zk_min_latency | 最小延时 |
zk_packets_received | 收包数 |
zk_packets_sent | 发包数 |
zk_num_alive_connections | 连接数 |
zk_outstanding_requests | 堆积请求数 |
zk_server_state | leader/follower状态 |
zk_znode_count | znode数量 |
zk_watch_count | watch数量 |
zk_ephemerals_count | 临时节点(znode) |
zk_approximate_data_size | 数据大小 |
zk_open_file_decriptor_count | 打开的文件描述符数量 |
zk_max_file_descriptor_count | 最大文件描述符数量 |