【Zookeeper学习六】——开源客户端ZKClient和Curator介绍与应用

前言

在真正的项目中通常使用的是zkclient和curator,而不是原生的zookeeper客户端,因为zookeeper原生的客户端存在一定的局限性,本篇小编主要讲解一下这两种zookeeper客户端的使用!

内容

1.1zk原生api不足之处:

  • 超时重连,不支持自动,需要手动操作
  • Watch注册一次后失效
  • 不支持递归创建节点

1.2zkclient

ZkClient是一个开源客户端,在Zookeeper原生API接口的基础上进行了包装,更便于开发人员使用。内部实现了Session超时重连,Watcher反复注册等功能。像dubbo等框架对其也进行了集成使用。

虽然ZkClient对原生API进行了封装,但也有它自身的不足之处:

  • 几乎没有参考文档;
  • 异常处理简化(抛出RuntimeException);
  • 重试机制比较难用;
  • 没有提供各种使用场景的实现;
    zkclient简单代码示例:
package com.zk.dev.zkClient.day1;  

import org.I0Itec.zkclient.IZkDataListener;  
import org.I0Itec.zkclient.ZkClient;  
import org.junit.After;  
import org.junit.Before;  
import org.junit.Test;  

import java.util.concurrent.TimeUnit;  

public class ZKTest  {  

    private ZkClient zk;  

    private String nodeName = "/test";  

    @Before  
    public void initTest() {  
        zk = new ZkClient("localhost:2181");  
    }  

    @After  
    public void dispose() {  
        zk.close();  
    }  

    @Test  
    public void testListener() throws InterruptedException {  
        // 监听指定节点的数据变化  

        zk.subscribeDataChanges(nodeName, new IZkDataListener() {  
            public void handleDataChange(String s, Object o) throws Exception {  
                System.out.println("node data changed!");  
                 System.out.println("node=>" + s);  
                 System.out.println("data=>" + o);  
                 System.out.println("--------------");  
            }  

            public void handleDataDeleted(String s) throws Exception {  
                System.out.println("node data deleted!");  
                System.out.println("s=>" + s);  
                System.out.println("--------------");  

            }  
        });  

                System.out.println("ready!");  

        // junit测试时,防止线程退出  
        while (true) {  
            TimeUnit.SECONDS.sleep(5);  
        }  
    }  

    @Test  
    public void testUpdateConfig() throws InterruptedException {  
        if (!zk.exists(nodeName)) {  
        //创建永久
            zk.createPersistent(nodeName);  
        }  
        zk.writeData(nodeName, "1");  
        zk.writeData(nodeName, "2");  
        zk.delete(nodeName);  
        zk.delete(nodeName);   
        zk.writeData("/test/ba", "bbb");  
    }  
}  

1.3Apache curator

  • Apache开源
  • 解决watcher的注册一次就失效
  • Api更加简单易用
  • 提供跟多解决方案并且实现:比如分布式锁
  • 提供常用的zookeeper工具类
  • 编程风格更爽

curator简单代码示例:

package com.zk.dev.zkClient.day1;  

import org.apache.curator.RetryPolicy;  
import org.apache.curator.framework.CuratorFramework;  
import org.apache.curator.framework.CuratorFrameworkFactory;  
import org.apache.curator.framework.recipes.cache.NodeCache;  
import org.apache.curator.framework.recipes.cache.NodeCacheListener;  
import org.apache.curator.framework.recipes.cache.PathChildrenCache;  
import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent;  
import org.apache.curator.framework.recipes.cache.PathChildrenCacheListener;  
import org.apache.curator.framework.recipes.cache.PathChildrenCache.StartMode;  
import org.apache.curator.retry.ExponentialBackoffRetry;  
import org.apache.zookeeper.CreateMode;  
import org.apache.zookeeper.ZooDefs.Ids;  

/** 
 * @see 测试curator框架例子 
 * @Author:xuehan 
 * @Date:2016年5月14日下午8:44:49 
 */  
public class CuratorUtils {  

    public String connectString = "localhost:2181";  
    CuratorFramework  zkclient = null ;  
    public CuratorUtils(){  
        /** 
         * connectString连接字符串中间用分号隔开,sessionTimeoutMs session过期时间,connectionTimeoutMs连接超时时间,retryPolicyc连接重试策略 
         */  
        //CuratorFrameworkFactory.newClient(connectString, sessionTimeoutMs, connectionTimeoutMs, retryPolicy)  
        // fluent风格aip   
  //    CuratorFrameworkFactory.builder().sessionTimeoutMs(5000).connectString(connectString).namespace("/test").build();  
        // 重连策略,没1一秒重试一次,最大重试次数3次  
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);  
        zkclient = CuratorFrameworkFactory.builder().connectString(connectString).sessionTimeoutMs(5000).retryPolicy(retryPolicy).namespace("tests").build();  
        zkclient.start();  
    }  
    /** 
     * 递归创建节点 
     * @param path 
     * @param data 
     * @throws Exception 
     */  
    public void createNode(String path, byte[] data) throws Exception{  
        zkclient.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).withACL(Ids.OPEN_ACL_UNSAFE).forPath(path, data);  
    }  
    /** 
     * 递归删除节点 
     * @param path 
     * @throws Exception 
     */  
    public void delNode(String path) throws Exception{  
        zkclient.delete().guaranteed().deletingChildrenIfNeeded().forPath(path);  
    }   public void zkClose(){  
        zkclient.close();  
    }  
    public void delNodeCallBack(String path) throws Exception{  
        zkclient.delete().guaranteed().deletingChildrenIfNeeded().inBackground(new DeleteCallBack()).forPath(path);  
    }      
    public void dataChanges(String path) throws Exception{  
        final NodeCache  dataWatch =  new NodeCache(zkclient, path);  
        dataWatch.start(true);  
        dataWatch.getListenable().addListener(new NodeCacheListener(){  

            public void nodeChanged() throws Exception {  
                System.out.println("path==>" + dataWatch.getCurrentData().getPath() + "==data==>" + new String(dataWatch.getCurrentData().getData()));  
            }  

        });  
        zkclient.delete().guaranteed().deletingChildrenIfNeeded().inBackground(new DeleteCallBack()).forPath(path);  
    }      
    public void addChildWatcher(String path) throws Exception{  
        final PathChildrenCache pc = new PathChildrenCache(zkclient, path, true);  
        pc.start(StartMode.POST_INITIALIZED_EVENT);  
        System.out.println("节点个数===>" + pc.getCurrentData().size());  
        pc.getListenable().addListener(new  PathChildrenCacheListener() {  

            public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception {  
                System.out.println("事件监听到"  + event.getData().getPath());  
                if(event.getType().equals(PathChildrenCacheEvent.Type.INITIALIZED)){  
                    System.out.println("客户端初始化节点完成"  + event.getData().getPath());  
                }else if(event.getType().equals(PathChildrenCacheEvent.Type.CHILD_ADDED)){  
                    System.out.println("添加节点完成"  + event.getData().getPath());  
                }else if(event.getType().equals(PathChildrenCacheEvent.Type.CHILD_REMOVED)){  
                    System.out.println("删除节点完成"  + event.getData().getPath());  
                }else if(event.getType().equals(PathChildrenCacheEvent.Type.CHILD_UPDATED)){  
                    System.out.println("修改节点完成"  + event.getData().getPath());  
                }  
            }  
        });  

    }  
    /*运行线程*/  
    public static void main(String[] args) throws Exception{  
        CuratorUtils cu = new CuratorUtils();  
        cu.zkclient.setData().forPath("/aa", "love is not".getBytes());  
        cu.addChildWatcher("/aa");  
        try{  
            Thread.sleep(20000000);  
        }catch(Exception e){};  
    }  
 }  

curator结合spring:

pom中引入:

 <dependency>
                <groupId>org.apache.curator</groupId>
                <artifactId>curator-framework</artifactId>
                <version>${curator.version}</version>
            </dependency>
            <dependency>
                <groupId>org.apache.curator</groupId>
                <artifactId>curator-recipes</artifactId>
                <version>${curator.version}</version>
            </dependency>
            <!-- curator(zookeeper的客户端)包 -->
            <dependency>
                <groupId>org.apache.curator</groupId>
                <artifactId>curator-client</artifactId>
                <version>${curator.version}</version>
            </dependency>
  <!--zookeeper重试策略-->
    <bean id="retryPolicy" class="org.apache.curator.retry.RetryNTimes">
      <!--重试次数-->
      <constructor-arg index="0" value="10"></constructor-arg>
     <!--每次的间隔-->
      <constructor-arg index="1" value="5000"></constructor-arg>
  </bean>

    <!--zookeeper客户端-->
    <bean id="client" class="org.apache.curator.framework.CuratorFrameworkFactory" factory-method="newClient" init-method="start">
        <constructor-arg index="0" value="192.168.25.131:2181"/>
        <!--session timeout 会话超时时间-->
        <constructor-arg index="1" value="10000"/>
        <!--创建连接的超时时间-->
        <constructor-arg index="2" value="5000"/>
        <!--重试策略-->
        <constructor-arg index="3" ref="retryPolicy"/>
    </bean>

猜你喜欢

转载自blog.csdn.net/changyinling520/article/details/80974871
今日推荐