当前位置: 首页 > news >正文

Zookeeper客户端Curator---Getting Started

先说个小插曲,前几天有个网站转载我的文章没有署名作者,我有点不开心就给他们留言了,然后今天一看他们把文章删了。其实我的意思并不是你允许转载,我想表达的是我的付出需要被尊重。也不知道是谁的错~

==================================

官网上的入门教程非常简单,如下:

学习Zookeeper

使用Curator的用户默认是了解Zookeeper的,Zookeeper的入门在这里:http: //zookeeper.apache.org/doc/trunk/zookeeperStarted.html

使用Curator

Curator的jar包可以从Maven中央仓库获得。各种工具罗列在主页上 main page。Maven,Gradle,Ant等用户可以轻松地将Curator包含进其构建脚本中。

大多数用户希望使用Curator的预制recipes(基于framework,提供高级特性),所以,curator-recipes是个正确的选择。如果您只想使用Zookeeper添加连接管理和重试策略的封装好的工具,那么使用curator-framework。

获取一个连接

Curator使用流式风格。如果你之前没有使用过这个,可能看起来很奇怪,因此建议您事先熟悉一下风格。ps:其实就是链式风格(Demo demo = new DemoBuilder().first().second().last().build();)

Curator连接的实例(CuratorFramework)来自于CuratorFrameworkFactory。每一个你连接的Zookeeper集群只需要一个CuratorFramework实例:

CuratorFrameworkFactory.newClient(zookeeperConnectionString, retryPolicy)

 

这将会使用默认值去连接一个Zookeeper集群。唯一需要指定的是 重试策略。大多数情况下,您应该使用:

RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3)
CuratorFramework client = CuratorFrameworkFactory.newClient(zookeeperConnectionString, retryPolicy);
client.start();

 

客户端必须启动(不再使用必须关闭)

直接调用Zookeeper

一旦你有一个CuratorFramework实例,你可以直接调用ZooKeeper,就像使用ZooKeeper中提供的原始Zookeeper对象一样。例如:

client.create().forPath("/my/path", myData)

 

这里的好处是:由CuratorFramework管理Zookeeper连接,并且当出现连接问题时会重试。

Recipes(高级特性)

分布式锁

InterProcessMutex lock = new InterProcessMutex(client, lockPath);
if ( lock.acquire(maxWait, waitUnit) ) 
{
    try 
    {
        // do some work inside of the critical section here
    }
    finally
    {
        lock.release();
    }
}

Leader选举

LeaderSelectorListener listener = new LeaderSelectorListenerAdapter()
{
    public void takeLeadership(CuratorFramework client) throws Exception
    {
        // this callback will get called when you are the leader
        // do whatever leader work you need to and only exit
        // this method when you want to relinquish leadership
    }
}

LeaderSelector selector = new LeaderSelector(client, path, listener);
selector.autoRequeue();  // not required, but this is behavior that you will probably expect
selector.start();

 

更多的特性翻译接下来的文章会有。

一个小例子

 导入的jar包:

curator-recipes这个包没用到,ZkClient那个包是另外一个客户端,这里也用不到,除了这两个其他都是要导入的

package zookeeper.curator;

import java.util.List;

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.data.Stat;

public class CuratorBase {

    private static String connectString = "192.168.127.129:2181,192.168.127.130:2181,192.168.127.131:2181";
    
    public static void main(String[] args) throws Exception {
        
        // 重试策略,初试时间1s,重试3次
        RetryPolicy policy = new ExponentialBackoffRetry(1000, 3);
        
        CuratorFramework curator = CuratorFrameworkFactory.newClient(connectString, policy);
        curator.start();
        //获取状态
        System.out.println(curator.getState());
        
        System.out.println("============Create=============");
        //创建节点
        String cPath1 = curator.create()
                .creatingParentsIfNeeded()
                .withMode(CreateMode.PERSISTENT).inBackground(new BackgroundCallback() {
            
            @Override
            public void processResult(CuratorFramework curatorFramework, CuratorEvent event) throws Exception {
                System.out.println(">>>>>>>>>>>>>>>>>>>>>>>");
                System.out.println("Code:" + event.getResultCode());
                System.out.println("Name:" + event.getName());
                System.out.println("Path:" + event.getPath());
                System.out.println("Type:" + event.getType());
                System.out.println("CurrentThread:" + Thread.currentThread().getName());
                System.out.println("<<<<<<<<<<<<<<<<<<<<<<<");
            }
        }).forPath("/root/rt", "123".getBytes());
        System.out.println("MainThread:" + Thread.currentThread().getName());
        Thread.sleep(2000); //暂停2s,为了等异步执行完,否则下面会报错:KeeperErrorCode = NoNode for /root/rr
        System.out.println(cPath1);
        String cPath2 = curator.create().withMode(CreateMode.PERSISTENT).forPath("/root/rr", "456".getBytes());
        System.out.println(cPath2);
        String cPath3 = curator.create().withMode(CreateMode.PERSISTENT).forPath("/root/re", "789".getBytes());
        System.out.println(cPath3);
        
        System.out.println("===========getData==============");
        //获取节点数值
        byte[] data = curator.getData().forPath("/root/rt");
        System.out.println("数值:" + new String(data));
        
        System.out.println("============setData=============");
        //修改节点数据
        Stat stat = curator.setData().forPath("/root/rt", "abc".getBytes());
        System.out.println(stat);
        
        System.out.println("============getChildren=============");
        //获取子节点
        List<String> childPath = curator.getChildren().forPath("/root");
        for (String path : childPath) {
            System.out.println(path + ":" + new String(curator.getData().forPath("/root/" + path)));
        }
        
        System.out.println("============Detele=============");
        //删除节点
        curator.delete().forPath("/root/rt");
        System.out.println("是否存在:" + curator.checkExists().forPath("/root/rt"));
        curator.delete().deletingChildrenIfNeeded().forPath("/root");
        System.out.println("是否存在:" + curator.checkExists().forPath("/root"));
        
        
        curator.close();      //关闭
        
    }
}

 log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<Configuration monitorInterval="1800">
    
    <Filter type="ThresholdFilter" level="trace"/>
    
      <Appenders>
          <Console name="console" target="SYSTEM_OUT">
            <!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
            <ThresholdFilter level="trace" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/>
        </Console>
      </Appenders>
      <Loggers>
        <Root level="WARN">
            <!-- TRACE < DEBUG < INFO < WARN < ERROR < FATAL
            -->
            <AppenderRef ref="console"/>
        </Root>
      </Loggers>
</Configuration>

 

结果:

STARTED
============Create=============
MainThread:main
>>>>>>>>>>>>>>>>>>>>>>>
Code:0
Name:/root/rt
Path:/root/rt
Type:CREATE
CurrentThread:main-EventThread
<<<<<<<<<<<<<<<<<<<<<<<
null
/root/rr
/root/re
===========getData==============
数值:123
============setData=============
51539607575,51539607578,1502067208571,1502067210604,1,0,0,0,3,0,51539607575

============getChildren=============
rr:456
rt:abc
re:789
============Detele=============
是否存在:null
是否存在:null

 

 关于代码也没啥可解释的,顾名思义。

比如creatingParentsIfNeeded(),就是如果需要的话就创建父节点,这个方法的好处是可以递归创建节点。

inBackground(new BackgroundCallback(){})这个就是异步创建节点啦,不阻塞线程。

 更多内容以后再说。

 

转载于:https://www.cnblogs.com/LUA123/p/7296359.html

相关文章:

  • [Step By Step]SAP HANA创建属性视图(Attribute View)
  • 如何在Linux上检测硬盘上的坏道和坏块
  • Linux高速下载工具——Axel
  • 低功耗M2M市场广阔 芯片设计如何降耗
  • 3.垃圾回收器
  • Debian下无root权限使用Python访问Oracle
  • bzoj 1860: [Zjoi2006]Mahjong麻将 题解
  • git使用点滴:如何查看commit的内容和git 获取最近一次提交的commit id
  • 美光Sun合作长寿命SLC闪存 100万次写入
  • OCZ新Summit系列固态硬盘强悍性能曝光
  • 用MAID 2.0降低存储费用
  • 为什么要创建开放源码的PlayScala社区?
  • 关于 TCP/IP,必知必会的十个问题
  • OSStatus code 查询
  • TCP协议中FLAG的含义
  • (三)从jvm层面了解线程的启动和停止
  • [译]前端离线指南(上)
  • django开发-定时任务的使用
  • Js基础知识(四) - js运行原理与机制
  • SpiderData 2019年2月16日 DApp数据排行榜
  • 开源中国专访:Chameleon原理首发,其它跨多端统一框架都是假的?
  • 快速构建spring-cloud+sleuth+rabbit+ zipkin+es+kibana+grafana日志跟踪平台
  • 蓝海存储开关机注意事项总结
  • 思考 CSS 架构
  • 一个完整Java Web项目背后的密码
  • 用Visual Studio开发以太坊智能合约
  • 继 XDL 之后,阿里妈妈开源大规模分布式图表征学习框架 Euler ...
  • ​ubuntu下安装kvm虚拟机
  • ​一帧图像的Android之旅 :应用的首个绘制请求
  • # 安徽锐锋科技IDMS系统简介
  • #周末课堂# 【Linux + JVM + Mysql高级性能优化班】(火热报名中~~~)
  • (06)Hive——正则表达式
  • (4)事件处理——(6)给.ready()回调函数传递一个参数(Passing an argument to the .ready() callback)...
  • (BFS)hdoj2377-Bus Pass
  • (pytorch进阶之路)CLIP模型 实现图像多模态检索任务
  • (翻译)Quartz官方教程——第一课:Quartz入门
  • (附源码)python房屋租赁管理系统 毕业设计 745613
  • (五)Python 垃圾回收机制
  • (一)pytest自动化测试框架之生成测试报告(mac系统)
  • (转)eclipse内存溢出设置 -Xms212m -Xmx804m -XX:PermSize=250M -XX:MaxPermSize=356m
  • (轉貼) 資訊相關科系畢業的學生,未來會是什麼樣子?(Misc)
  • (状压dp)uva 10817 Headmaster's Headache
  • .NET : 在VS2008中计算代码度量值
  • .NET Core WebAPI中使用swagger版本控制,添加注释
  • .NET 将多个程序集合并成单一程序集的 4+3 种方法
  • .net解析传过来的xml_DOM4J解析XML文件
  • .NET开发不可不知、不可不用的辅助类(三)(报表导出---终结版)
  • .net项目IIS、VS 附加进程调试
  • .NET中winform传递参数至Url并获得返回值或文件
  • .Net转Java自学之路—基础巩固篇十三(集合)
  • .one4-V-XXXXXXXX勒索病毒数据怎么处理|数据解密恢复
  • ?
  • @PreAuthorize注解
  • [ 蓝桥杯Web真题 ]-布局切换
  • [20140403]查询是否产生日志