Zookeeper学习----zookeeperAPI介绍及分布式注册发现简单实现

1. 导入依赖

注意导入的zookeeper包的版本必须和虚拟机安装的zookeeper版本一致。

  <dependency>
      <groupId>org.apache.zookeeper</groupId>
      <artifactId>zookeeper</artifactId>
      <version>3.4.6</version>
      
    </dependency>

2. API使用

2.1 创建zookeeper对象

  //通过CountDownLatch,实现异步的同步问题,使zookeeper创建成功在继续往下执行
        final CountDownLatch downLatch = new CountDownLatch(1);

        //异步创建zookeeper对象,不堵塞线程。
        //watcher为回调函数
        ZooKeeper zooKeeper = new ZooKeeper("192.168.45.27:2181,192.168.45.28:2181,192.168.45.29:2181,192.168.45.30:2181/test", //zookeeper集群节点信息
                3000,  //客户端断开连接,zookeeper保存连接session的时间
                new Watcher() {         //默认的watcher回调函数,session级别的。watcher回调,只发生在产生事件时。只有get和exist存在watch监听事件,其他操作都是事件的产生者
                    @Override
                    public void process(WatchedEvent watchedEvent) {
                        String path = watchedEvent.getPath();
                        System.out.println(path);
                        System.out.println(watchedEvent.toString());
                        switch (watchedEvent.getState()) {
                            case Unknown:
                                break;
                            case Disconnected:
                                break;
                            case NoSyncConnected:
                                break;
                            case SyncConnected:
                                System.out.println("initWatcher:Connected!");
                                downLatch.countDown();
                                break;
                            case AuthFailed:
                                break;
                            case ConnectedReadOnly:
                                break;
                            case SaslAuthenticated:
                                break;
                            case Expired:
                                break;
                        }
                        switch (watchedEvent.getType()) {
                            case None:
                                break;
                            case NodeCreated:
                                break;
                            case NodeDeleted:
                                break;
                            case NodeDataChanged:
                                break;
                            case NodeChildrenChanged:
                                break;
                        }

                    }
                });

        downLatch.await();   //等待zookeeper异步创建成功在继续执行。
        ZooKeeper.States state = zooKeeper.getState();
        switch (state) {
            case CONNECTING:
                System.out.println("zk.states.connecting!!");
                break;
            case ASSOCIATING:
                break;
            case CONNECTED:
                System.out.println("zk.states.connected!!");
                break;
            case CONNECTEDREADONLY:
                break;
            case CLOSED:
                break;
            case AUTH_FAILED:
                break;
            case NOT_CONNECTED:
                break;
        }

2.2 创建节点

同步方式:

public String create(String path, byte[] data, List<ACL> acl, CreateMode createMode) 
  1. path:创建节点的路径
  2. byte[] data 节点信息的字节数组
  3. acl 
    public interface Ids {
            Id ANYONE_ID_UNSAFE = new Id("world", "anyone");
            Id AUTH_IDS = new Id("auth", "");
            ArrayList<ACL> OPEN_ACL_UNSAFE = new ArrayList(Collections.singletonList(new ACL(31, ANYONE_ID_UNSAFE)));
            ArrayList<ACL> CREATOR_ALL_ACL = new ArrayList(Collections.singletonList(new ACL(31, AUTH_IDS)));
            ArrayList<ACL> READ_ACL_UNSAFE = new ArrayList(Collections.singletonList(new ACL(1, ANYONE_ID_UNSAFE)));
        }

     

  4. CreateMode createMode创建节点的模式

    public enum CreateMode {
        PERSISTENT(0, false, false),    //持久节点
        PERSISTENT_SEQUENTIAL(2, false, true),    //持久序列化节点
        EPHEMERAL(1, true, false),       //临时节点
        EPHEMERAL_SEQUENTIAL(3, true, true);    //临时序列化节点

    异步创建方式:

public void create(String path, byte[] data, List<ACL> acl, CreateMode createMode, StringCallback cb, Object ctx) {
StringCallback:表示创建成功的回调函数
 Object ctx:上下文对象

2.3 获取数据

同步方式一:

public byte[] getData(String path, Watcher watcher, Stat stat)
String path:节点路径
Watcher watcher:监听节点事件,如果节点产生事件,回调这个函数,只会回调一次
Stat stat:存储节点元数据信息

返回值:节点数据的字节数组

同步方式二:

public byte[] getData(String path, boolean watch, Stat stat)
 boolean watch:如果为true,就表示使用zookeeper对象参数中的默认watcher监听。为false就表示不进行事件监听。

异步方式一:

 public void getData(String path, Watcher watcher, DataCallback cb, Object ctx)
DataCallback cb:获取到数据后的回调函数
Object ctx:上下文对象

异步方式二:

 public void getData(String path, boolean watch, DataCallback cb, Object ctx)

2.4 修改节点信息

同步方式:

public Stat setData(String path, byte[] data, int version)
int version:数据的版本

异步方式:

public void setData(String path, byte[] data, int version, StatCallback cb, Object ctx)

2.5 节点是否存在

方式一:

public Stat exists(String path, Watcher watcher)

方式二:

 public Stat exists(String path, boolean watch) 

方式三:

 public void exists(String path, Watcher watcher, StatCallback cb, Object ctx)

方式四:

 public void exists(String path, boolean watch, StatCallback cb, Object ctx) 

3. 示例

案例:zookeeper中某个目录节点保存了多台服务的配置文件。多台服务需要根据zookeeper中的配置文件进行相关配置。zookeeper保存的配置文件可以进行增删改操作,相应的多台服务需要及时的进行配置文件同步。

获取zookeeper连接对象工具类

public class ZkUtil {

    private static ZooKeeper zk;
    private static String path = "192.168.45.27:2181,192.168.45.28:2181,192.168.45.29:2181/test";
    private static CountDownLatch countDownLatch = new CountDownLatch(1);

    public static ZooKeeper getZk(){
        DefaultWatcher defaultWatcher = new DefaultWatcher();
        defaultWatcher.setCountDownLatch(countDownLatch);
        try {
            zk = new ZooKeeper(path,300,defaultWatcher);
            countDownLatch.await();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return zk;
    }

}

 

public class DefaultWatcher implements Watcher {
    private CountDownLatch countDownLatch;

    public CountDownLatch getCountDownLatch() {
        return countDownLatch;
    }

    public void setCountDownLatch(CountDownLatch countDownLatch) {
        this.countDownLatch = countDownLatch;
    }

    @Override
    public void process(WatchedEvent watchedEvent) {
        switch (watchedEvent.getState()) {
            case Unknown:
                break;
            case Disconnected:
                break;
            case NoSyncConnected:
                break;
            case SyncConnected:
                System.out.println("zookeeper连接建立!!!!");
                countDownLatch.countDown();
                break;
            case AuthFailed:
                break;
            case ConnectedReadOnly:
                break;
            case SaslAuthenticated:
                break;
            case Expired:
                break;
        }

    }

watcher封装类:

public class GetExistWatcher implements Watcher,AsyncCallback.StatCallback,AsyncCallback.DataCallback {
    private ZooKeeper zk;
    private StringConf conf;

    private CountDownLatch latch = new CountDownLatch(1);

    public ZooKeeper getZk() {
        return zk;
    }

    public void setZk(ZooKeeper zk) {
        this.zk = zk;
    }

    public StringConf getConf() {
        return conf;
    }

    public void setConf(StringConf conf) {
        this.conf = conf;
    }

    public void aWait(){
        try {
            zk.exists("/appConf",this,this,"aaa");
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }


    /**
     * getData时调用的回调函数
     * @param i
     * @param s
     * @param o
     * @param bytes
     * @param stat
     */
    @Override
    public void processResult(int i, String s, Object o, byte[] bytes, Stat stat) {
        if(bytes != null){
            conf.setConf(new String(bytes));
            latch.countDown();
        }
    }

    /**
     * exist时调用的回调函数
     * @param i
     * @param s
     * @param o
     * @param stat
     */
    @Override
    public void processResult(int i, String s, Object o, Stat stat) {

        if(stat != null){
            zk.getData("/appConf",this,this,"");
        }
    }

    /**
     * watcher监听事件
     * @param watchedEvent
     */
    @Override
    public void process(WatchedEvent watchedEvent) {

        switch (watchedEvent.getType()) {
            case None:
                break;
            case NodeCreated:
                zk.getData("/appConf",this,this,"");
                break;
            case NodeDeleted:
                conf.setConf("");
                latch = new CountDownLatch(1);
                break;
            case NodeDataChanged:
                zk.getData("/appConf",this,this,"");
                break;
            case NodeChildrenChanged:
                break;
        }
    }
}

测试类:

public class TestConf {
    private ZooKeeper zk;

    @Before
    public void init(){
        zk = ZkUtil.getZk();
    }
    @After
    public void destory(){
        try {
            zk.close();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void testConf(){
        GetExistWatcher watcher = new GetExistWatcher();
        StringConf strConf = new StringConf();
        watcher.setZk(zk);
        watcher.setConf(strConf);

        watcher.aWait();


        while (true){
            if("".equals(strConf.getConf())){
                System.out.println("节点被删除了!!!!");
                watcher.aWait();
            }else {

                System.out.println(strConf.getConf());
            }
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }


    }

配置文件类:

public class StringConf {

    private String conf;

    public String getConf() {
        return conf;
    }

    public void setConf(String conf) {
        this.conf = conf;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值