Zookeeper客户端Curator使用入门

Curator简介

Curator官网:http://curator.apache.org/
Curator是Netflix公司开源的一套Zookeeper客户端框架。了解过Zookeeper原生API都会清楚其复杂度。Curator帮助我们在其基础上进行封装、实现一些开发细节,包括接连重连、反复注册Watcher和NodeExistsException等。目前已经作为Apache的顶级项目出现,是最流行的Zookeeper客户端之一。从编码风格上来讲,它提供了基于Fluent的编程风格支持。

除此之外,Curator还提供了Zookeeper的各种应用场景:Recipe、共享锁服务、Master选举机制和分布式计数器等。

Curator是Netflix公司开源的一个Zookeeper客户端,与Zookeeper提供的原生客户端相比,Curator的抽象层次更高,简化了Zookeeper客户端的开发量; 简单就是对Zookeeper的原生API做了一层封装 ,使用起来更加的方便。
Apache Curator 是分布式协调服务Apache ZooKeeper的 Java/JVM 客户端库。它包括一个高级 API 框架和实用程序,使使用 Apache ZooKeeper 变得更加容易和可靠。它还包括常见用例和扩展(例如服务发现和 Java 8 异步 DSL)的方法。

Zookeeper名字的由来是比较有趣的,下面的片段摘抄自《从PAXOS到ZOOKEEPER分布式一致性原理与实践》一书:
Zookeeper最早起源于雅虎的研究院的一个研究小组。在当时,研究人员发现,在雅虎内部很多大型的系统需要依赖一个类似的系统进行分布式协调,但是这些系统往往存在分布式单点问题。所以雅虎的开发人员就试图开发一个通用的无单点问题的分布式协调框架。在立项初期,考虑到很多项目都是用动物的名字来命名的(例如著名的Pig项目),雅虎的工程师希望给这个项目也取一个动物的名字。时任研究院的首席科学家Raghu Ramakrishnan开玩笑说:再这样下去,我们这儿就变成动物园了。此话一出,大家纷纷表示就叫动物园管理员吧——因为各个以动物命名的分布式组件放在一起,雅虎的整个分布式系统看上去就像一个大型的动物园了,而Zookeeper正好用来进行分布式环境的协调——于是,Zookeeper的名字由此诞生了。

Curator无疑是Zookeeper客户端中的瑞士军刀,它译作"馆长"或者’‘管理者’’,不知道是不是开发小组有意而为之,笔者猜测有可能这样命名的原因是说明Curator就是Zookeeper的馆长(脑洞有点大:Curator就是动物园的园长)

作者:zhrowable 链接:https://www.jianshu.com/p/70151fc0ef5d 来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

ZooKeeper 版本 3.4.x 与Curator 兼容性

链接:http://curator.apache.org/zk-compatibility-34.html

ZooKeeper 3.4.x 现已停产。因此,最新版本的 Curator 已取消对它的支持。如果您希望将 Curator 与ZooKeeper 3.4.x 一起使用,您应该固定到 Curator 的 4.2.x 版。Curator 4.2.x 以软兼容模式支持
ZooKeeper 3.4.x 集成。要使用此模式,您必须在将 Curator 添加到依赖项管理工具时排除 ZooKeeper。

添加maven

<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-recipes</artifactId>
    <version>4.2.0</version>
    <exclusions>
        <exclusion>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
        </exclusion>
    </exclusions>
</dependency>

您还必须添加对 ZooKeeper 3.4.x 的依赖。

Curator 将检测正在使用的 ZooKeeper 库,并根据需要自动设置 ZooKeeper 3.4 兼容模式。
参考:https://www.cnblogs.com/LUA123/p/10288797.html

Maven依赖

Curator的jar包已经发布到Maven中心,由以下几个artifact的组成。根据需要选择引入具体的artifact。但大多数情况下只用引入curator-recipes即可。
在这里插入图片描述
curator-framework:对zookeeper的底层api的一些封装
curator-client:提供一些客户端的操作,例如重试策略等
curator-recipes:封装了一些高级特性,如:Cache事件监听、选举、分布式锁、分布式计数器、分布式Barrier等

<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-recipes</artifactId>
    <version>4.2.0</version>
    <exclusions>
        <exclusion>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
        </exclusion>
    </exclusions>
</dependency>

Curator实现Zookeeper分布式锁

demo1

public static void main(String[] args) throws Exception {

//创建zookeeper的客户端

RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);

CuratorFramework client = CuratorFrameworkFactory.newClient("ipAddressOne,ipAddressTwo,ipAddressThree", retryPolicy);

client.start();

//创建分布式锁, 锁空间的根节点路径为/curator/lock

InterProcessMutex mutex = new InterProcessMutex(client, "/curator/mylock");

mutex.acquire();

//获得了锁, 进行业务流程

System.out.println("Enter mutex");

//完成业务流程, 释放锁

mutex.release();

//关闭客户端

client.close();

}

demo2

package cn.distri.util;

import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.apache.curator.retry.ExponentialBackoffRetry;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class zkdisutil {

    private static String address = "10.123.10.15:2181";

    public static void main(String[] args) {
        //1、重试策略:初试时间为1s 重试3次
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
        //2、通过工厂创建连接
        CuratorFramework client = CuratorFrameworkFactory.newClient(address, retryPolicy);
        //3、开启连接
        client.start();
        //4 分布式锁
        final InterProcessMutex mutex = new InterProcessMutex(client, "/curator/lock");
        //读写锁
        //InterProcessReadWriteLock readWriteLock = new InterProcessReadWriteLock(client, "/readwriter");

        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);

        for (int i = 0; i < 5; i++) {
            fixedThreadPool.submit(new Runnable() {
                @Override
                public void run() {
                    boolean flag = false;
                    try {
                        //尝试获取锁,最多等待5秒
                        flag = mutex.acquire(5, TimeUnit.SECONDS);
                        Thread currentThread = Thread.currentThread();
                        if(flag){
                            System.out.println("线程"+currentThread.getId()+"获取锁成功");
                        }else{
                            System.out.println("线程"+currentThread.getId()+"获取锁失败");
                        }
                        //模拟业务逻辑,延时4秒
                        Thread.sleep(4000);
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally{
                        if(flag){
                            try {
                                mutex.release();
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
            });
        }
    }
}

demo3

package cn.distri.util;

import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.curator.retry.RetryNTimes;
import java.util.concurrent.TimeUnit;

public class ZKDistributeUtil {


	private static final String ZK_ADDRESS = "10.213.10.15:2181";
    private static final String ZK_LOCK_PATH = "/zktest";
    public static void main(String[] args) throws InterruptedException {
        // 1.Connect to zk
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
        CuratorFramework client = CuratorFrameworkFactory.newClient(ZK_ADDRESS, retryPolicy);
        client.start();
        System.out.println("zk client start successfully!");
        Thread t1 = new Thread(() -> {doWithLock(client);},"t1");
        Thread t2 = new Thread(() -> {doWithLock(client);},"t2");
         t1.start();
         t2.start();
    }

         private static void doWithLock(CuratorFramework client) {
            InterProcessMutex lock = new InterProcessMutex(client, ZK_LOCK_PATH);

            try {
                if (lock.acquire(10 * 1000, TimeUnit.SECONDS)) {
                System.out.println(Thread.currentThread().getName() + " hold lock");
                Thread.sleep(5000L);
                System.out.println(Thread.currentThread().getName() + " release lock");
               }
             } catch (Exception e) {
                e.printStackTrace();
             } finally {
              try {
                lock.release();
               } catch (Exception e) {
                e.printStackTrace();
               }
            }
    }
}

CuratorUtil 工具类

package cn.zmz.util;

import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
 * @author 
 * @date  2021-6-23 10:30:16
 */
@Component
public class CuratorUtil {

    @Value("${zookeeper.address}")
    private  String zkAddress;

    public  CuratorFramework getCuratorClient() {
        //1、重试策略:初试时间为1s 重试3次
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
        //2、通过工厂创建连接
        CuratorFramework client = CuratorFrameworkFactory.newClient(zkAddress, retryPolicy);
        //3、开启连接
        client.start();
        return client;
    }
}

其他博文

https://blog.51cto.com/zero01/2109137
https://blog.csdn.net/wo541075754/article/details/69138878
https://www.jianshu.com/p/70151fc0ef5d
https://blog.csdn.net/u010889616/article/details/80209629
https://www.cnblogs.com/seaspring/p/5536338.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值