zookeeper的开源客户端curator

一.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)之间请求和应答之间能容忍的最多心跳数
electionAlg0.基于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)配置说明

属性含义
ipip地址
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.namehost信息
java.versionjava版本
jva.vendor供应商
java.home运行环境所在目录
java.class.pathclasspath
java.library.path第三方库指定非java类包的位置(如:dll,so)
java.io.tmpdir默认的临时文件路径
java.compilerJIT编译器的名称
os.nameLInux
os.archamd64
os.version3.10.0-514.el7.x86_64
user.namezookeeper【用户名】
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-pathswatch节点数
watcherswatcher数量

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_stateleader/follower状态
zk_znode_countznode数量
zk_watch_countwatch数量
zk_ephemerals_count临时节点(znode)
zk_approximate_data_size数据大小
zk_open_file_decriptor_count打开的文件描述符数量
zk_max_file_descriptor_count最大文件描述符数量

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值