zookeeper(reactive模型)分布式集中配置简单应用

  1. 环境准备
    1.1 准备三台装有zookeeper集群的主机(192.168.61.134,192.168.61.130,192.168.61.135),并启动zk。
    1.2 开发环境springboot,jkd1.8。
  2. 代码实现
    2.1 连接zk工具类
package com.my.zk.zookeeperdemo.conf;

import org.apache.zookeeper.ZooKeeper;

import java.io.IOException;
import java.util.concurrent.CountDownLatch;

public class ZkUtils {
    private static ZooKeeper zk;
    private static String zk_address = "192.168.61.134:2181,192.168.61.130:2181,192.168.61.135:2181/testConf";
//    private static String zk_address = "192.168.61.134:2181,192.168.61.130:2181,192.168.61.135:2181/testLock";
    private static DefaultWatch defaultWatch = new DefaultWatch();
    //countDonwLatch是为了保证zk连接成功后返回可用的zk对象,连接成功之前阻塞
    private static CountDownLatch init = new CountDownLatch(1);
    public static  ZooKeeper getZk(){
        try {
            zk = new ZooKeeper(zk_address,1000,defaultWatch);
            defaultWatch.setCc(init);
            init.await();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return zk;
    }
}

2.2 监控连接的Watch

package com.my.zk.zookeeperdemo.conf;

import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;

import java.util.concurrent.CountDownLatch;

public class DefaultWatch implements Watcher {
    CountDownLatch cc;
    public void setCc(CountDownLatch cc){
        this.cc = cc;

    }
    @Override
    public void process(WatchedEvent watchedEvent) {
        switch(watchedEvent.getState()){

            case Unknown:
                break;
            case Disconnected:
                break;
            case NoSyncConnected:
                break;
            case SyncConnected:
                //连接成功后减一,执行Zkutils中的await()方法
                cc.countDown();
                break;
            case AuthFailed:
                break;
            case ConnectedReadOnly:
                break;
            case SaslAuthenticated:
                break;
            case Expired:
                break;
        }
    }
}

2.3 监控节点状态的Watch

package com.my.zk.zookeeperdemo.conf;

import org.apache.zookeeper.AsyncCallback;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;

import java.util.concurrent.CountDownLatch;

public class WatchCallBack implements Watcher, AsyncCallback.StatCallback, AsyncCallback.DataCallback {
    ZooKeeper zk;
    //zookeeper异步线程与工作线程共享数据的对象(工作线程接收数据用的)
    MyConf myConf;
    CountDownLatch countDownLatch = new CountDownLatch(1);
    public MyConf getMyConf() {
        return myConf;
    }

    public void setMyConf(MyConf myConf) {
        this.myConf = myConf;
    }

    public ZooKeeper getZk() {
        return zk;
    }

    public void setZk(ZooKeeper zk) {
        this.zk = zk;
    }
    public void aWait(){
        //走这一步之前如果没有CountDownLatch(1)控制,执行该步骤的时候是不会阻塞的
        zk.exists("/AppConf",this,this,"abc");
        try {
            //阻塞,等待判断节点存在,并且getData执行完,再countDown(),避免取不到数据
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    @Override
    public void processResult(int i, String s, Object o, byte[] bytes, Stat stat) {
        if(null != bytes){
            String data = new String(bytes);
            myConf.setConf(data);
            //此时zookeeper的线程已经返回数据了
            countDownLatch.countDown();
        }
    }

    @Override
    public void processResult(int i, String s, Object o, Stat stat) {
        // stat 如果不是null,代表节点存在,可以调用getData()方法取数据了
        if (null != stat){
            //触发第一个回调
            zk.getData("/AppConf",this,this,"abc");
        }
    }

    @Override
    public void process(WatchedEvent watchedEvent) {
        switch (watchedEvent.getType()){

            case None:
                break;
            case NodeCreated:
                System.out.println("该节点被创建了。。。。。");
                zk.getData("/AppConf",this,this,"abc");
                break;
            case NodeDeleted:
                System.out.println("该节点被删除了,服务阻塞中。。。。。");
//                节点被删除了,对应的数据对象也要清空,重新阻塞工作线程
                myConf.setConf("");
                countDownLatch = new CountDownLatch(1);
                break;
            case NodeDataChanged:
                System.out.println("该节点的值被改变了。。。。。");
                zk.getData("/AppConf",this,this,"abc");
                break;
            case NodeChildrenChanged:
                break;
        }
    }
}

2.4 数据共享层

package com.my.zk.zookeeperdemo.conf;

/**
 * 用于接收zookeeper异步返回的数据
 */
public class MyConf {
    private String conf;

    public String getConf() {
        return conf;
    }

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

2.5 测试类

package com.my.zk.zookeeperdemo;

import com.my.zk.zookeeperdemo.conf.MyConf;
import com.my.zk.zookeeperdemo.conf.WatchCallBack;
import com.my.zk.zookeeperdemo.conf.ZkUtils;
import org.apache.zookeeper.AsyncCallback;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;
import org.junit.After;
import org.junit.Before;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class ZookeeperdemoApplicationTests {
    ZooKeeper zk;

    /*@Before
    void conn() {
        zk = ZkUtils.getZk();
        System.out.println(null == zk?"zk连接失败":"zk连接成功");
    }*/

    @After
    void close(){
        try {
            zk.close();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Test
    void getConf(){
        zk = ZkUtils.getZk();
        System.out.println(null == zk?"zk连接失败":"zk连接成功");
        WatchCallBack watchCallBack = new WatchCallBack();
        watchCallBack.setZk(zk);
        MyConf myConf = new MyConf();
        watchCallBack.setMyConf(myConf);
        watchCallBack.aWait();
        //以下部分是真正的业务逻辑代码部分
        while (true){
            if (("").equals(myConf.getConf())){
                System.out.println("节点被删除了,丢失了。。。。。。。");
                watchCallBack.aWait();
            }else {
//                System.out.println(myConf.getConf());
            }
            try {
                System.out.println("打印配置数据:"+myConf.getConf());
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

2.6 执行结果(获取/testConf/AppConf节点中的共享配置)
在这里插入图片描述

  1. 注意运行前,需要在zk中先创建好需要监控的节点
    在这里插入图片描述
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值