zookeeper集群实现配置中心

zookeeper集群实现配置中心

引言

上篇写了搭建zookeeper集群的笔记,此篇就用此集群作为配置中心,使用zookeeper的api,实现配置的热加载。

实验场景

起一个服务,动态加载zookeeper中的配置,根据配置的Class路径,反射获得不同的对象,执行不同的方法。

具体步骤

一、添加zookeeper依赖
       <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.6</version>
        </dependency>
二、封装zookeeper对象获取工具类

该类封装了zookeeper对象的获得过程,可以直接通过其获得zookeeper对象。

public class ZKUtil {
    private static ZooKeeper zk;
    private static String urls = "192.168.128.128:2181,192.168.128.132:2181" +
            ",192.168.128.130:2181,192.168.128.131:2181/testLock";
    private DefaltWatch watcher = new DefaltWatch();
    private CountDownLatch countDownLatch = new CountDownLatch(1);

    public ZooKeeper getZk() {
        try {

            zk = new ZooKeeper(urls,1000,watcher);
            watcher.setCc(countDownLatch);
            countDownLatch.await();

        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
        // 加个锁防止zk还没连接到
        return zk;
    }

}
三、自定义监听类

该类充当监听器,这里主要用于实例化zookeeper时,监听实例化过程。为了保证成功建立连接后才返回对象。

public class DefaultWatch implements Watcher {
    CountDownLatch cc;

    public void setCc(CountDownLatch cc) {
        this.cc = cc;
    }

    @Override
    public void process(WatchedEvent watchedEvent) {

        Event.KeeperState state = watchedEvent.getState();

        switch (state) {
            case Unknown:
                break;
            case Disconnected:
                break;
            case NoSyncConnected:
                break;
            case SyncConnected:
                System.out.println("zookeeper connectioned");
                cc.countDown();
                break;
            case AuthFailed:
                break;
            case ConnectedReadOnly:
                break;
            case SaslAuthenticated:
                break;
            case Expired:
                break;
        }
    }
}
四、自定义配置定义类

其属性对应zookeeper中配置的信息。

public class MyConfig {
    private String className;
}
五、封装回调监听类

该类是zookeeper的核心类,使用zookeeper watch的功能,配合回调,zookeeper中配置文件更新时,动态加载配置信息。

public class WatchCallback implements Watcher, AsyncCallback.StatCallback, AsyncCallback.DataCallback {

    ZooKeeper zk;

    MyConfig config;

    CountDownLatch cc = new CountDownLatch(1);


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

    public void setConfig(MyConfig config) {
        this.config = config;
    }

    /**
     * 回调getData, 看bytes数组
     * @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 ){
            config.setClassName(new String(bytes));
            cc.countDown();
        }

    }

    /**
     * 回调exists
     * @param i
     * @param s
     * @param o
     * @param stat
     */
    @Override
    public void processResult(int i, String s, Object o, Stat stat) {
        if(stat != null) {
            System.out.println("exist");

            zk.getData("/testConfig", this, this, "aaa");

        }
    }

    /**
     * 第一次是监听exist的
     * 监听getData
     * @param watchedEvent
     */
    @Override
    public void process(WatchedEvent watchedEvent) {

        Event.EventType type = watchedEvent.getType();

        switch (type) {
            case None:
                break;
            case NodeCreated:
                zk.getData("/testConfig",this,this,"aaa");

                break;
            case NodeDeleted:
                config.setClassName("");

                cc = new CountDownLatch(1);

                break;
            case NodeDataChanged:
                zk.getData("/testConfig",this,this,"aaa");
//                cc.countDown();
                break;
            case NodeChildrenChanged:
                break;
        }


    }

    // 判断是否存在,设置监听器和回调函数
    public void await() {
        // 回调后监听交给getData了
        zk.exists("/testConfig",this,this,"ccc");
        try {
            cc.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
六、创建接口和实例

接口

public interface ObjectParent {
    String sayHello();
}

实现类一

public class Object1 implements ObjectParent{

    @Override
    public String sayHello() {
        return "hello Object1";
    }
}

实现类二

public class Object2 implements ObjectParent {

    @Override
    public String sayHello() {
        return "hello Object2";
    }
}
七、编写main类实现

以下代码通过zookeeper配置类的名称,通过反射获得对应类的对象,调用对应的方法。

public static void main(String[] args) {
        WatchCallback watchCallback = new WatchCallback();

        ZookeeperUtil zkUtil = new ZookeeperUtil();
        ZooKeeper zk = zkUtil.getZookeeper();
    
        MyConfig conf = new MyConfig();
        watchCallback.setConfig(conf);
        watchCallback.setZk(zk);
        watchCallback.await();
        ObjectParent objectParent;
        try {
            while(true) {
                Class cl  = Class.forName(conf.getClassName());
                objectParent = (ObjectParent) cl.newInstance();
                System.out.println(objectParent.sayHello());
            }
        }catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException classNotFoundException) {
            classNotFoundException.printStackTrace();
        }

    }
实验结果

zookeeper输入create /testConfig/testConfig com.test.zookeeper.Object1

输出 hello Object1

zookeeper输入create /testConfig/testConfig com.test.zookeeper.Object1

输出 hello Object2

写在最后

本篇通过,小例子实现zookeeper做为配置中心的玩法,可以自行研究,解锁更多用法。下篇将用zookeeper实现分布式锁。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

平平安安年年

一起学习,一起成长

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值