Zookeeper--实现分布式配置中心

一、zk实现分布式配置中心代码实现:

在Zk里增加一个目录节点/username,并把配置信息存储到里面
在这里插入图片描述
引入zk的依赖

    <!--        引入zk依赖-->
            <dependency>
                <groupId>org.apache.zookeeper</groupId>
                <artifactId>zookeeper</artifactId>
                <version>3.4.14</version>
            </dependency>

实现代码:

    public class ZookeeperProSync  implements Watcher {
    
        private static CountDownLatch connectedSemaphore = new CountDownLatch(1);
        private static ZooKeeper zk = null;
        //用于统计ZKnode的元数据信息
        private  static Stat stat = new Stat();
    
        public static void main(String[] args) {
            //zookeeper配置数据存放路径,相当于在zk下新建一个存放数据节点的目录
            String path = "/username";
            try {
                //连接zk并注册一个默认的监听器,其中192.168.199.11:2181是zk提供客户端连接的主机端口地址
                //sessionTimeout的值表示客户端和服务端保持连接,心跳超时的时间。因为zk客户端和服务端是基于长连接的。所以服务器会和客户端使用
                //心跳机制保持连接状态,一旦超过指定心跳时间没回复,就把客户端剔除。
                zk =  new ZooKeeper("192.168.199.11:2181",5000,new ZookeeperProSync() );
                //等待zk连接成功的通知
                connectedSemaphore.await();
                //获取path目录节点的配置数据,并注册默认的监听器。 其中zk.getData相当于zk的get命令,去指定的目录下获取数据。
                //而该方法的第二个参数watch=true表明当前客户端设置了一个监听器在zk的path目录下,只要path目录有变动,就立刻的
                //发送一个监听事件回来通知客户端。
                System.out.println(new String(zk.getData(path,true,stat)));
                //模拟程序一直在运行
                Thread.sleep(Integer.MAX_VALUE);
            } catch (IOException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (KeeperException e) {
                e.printStackTrace();
            }
        }
    
        //zk监听事件处理逻辑。
        public void process(WatchedEvent watchedEvent) {
            //zk成功连接的通知事件
            if(Event.KeeperState.SyncConnected  == watchedEvent.getState()){
            //这一步的意义是当客户端和服务器连接成功,会调用process方法,而此时只是表示连接成功,即Event.EventType.None ,并没有说明任何节点发生改变。故此做这个判断,让main方法去获取连接成功后,最新的path下的数据,并且重新注册一个监听器监视自己感兴趣的目录
                if(Event.EventType.None == watchedEvent.getType() && null == watchedEvent.getPath()){
                    connectedSemaphore.countDown();
                }else if (watchedEvent.getType() == Event.EventType.NodeDataChanged){
                   //zk目录节点数据发生变化的通知事件
                   try {
                       System.out.println("配置已被修改,新值为:"+new String(zk.getData(watchedEvent.getPath(),true,stat)));
                   }catch (Exception e){
                       e.printStackTrace();
                   }
                }
    
            }
        }
    }

启动,开始监听zk的username目录,然后在zk服务端建立username目录,并添加数据节点,然后再修改数据节点:

numChildren = 2
[zk: localhost:2181(CONNECTED) 14] create /username haizhang66666666
Created /username
[zk: localhost:2181(CONNECTED) 17] set /username haizhang777777
cZxid = 0x6
ctime = Tue Apr 28 17:38:58 CST 2020
mZxid = 0xa
mtime = Tue Apr 28 17:39:19 CST 2020
pZxid = 0x6
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 14
numChildren = 0

得到的结果:
在这里插入图片描述
此时当目录下的数据节点发生修改时,就可以监听到了。

对于WatchedEvent讲解
watchEvent里面有几个事件:

        public static enum EventType {
                None(-1),              //和服务器端建立连接时的事件
                NodeCreated(1),        //当节点创建时的事件
                NodeDeleted(2),        //当节点删除时的事件
                NodeDataChanged(3),    //当节点下的数据状态发生修改时的事件
                NodeChildrenChanged(4);//当节点下的目录结构发生变动的事件。
        }

我们可以把断点定位图下:
在这里插入图片描述
可以发现,当成功和zk连接的时候,EventType时None类型的,并且path=null。
如果连接超时,或者心跳检测超时没回应,就会有下面的报错
在这里插入图片描述
表示当前客户端已经被zk剔除了。

二、注意点:

zookeeper的监听事件是一次性的
并不会包括任何数据,如果你想要获取到最新改变的数据,就得重新查询,并且重新设置监听(因为zk监听事件是一次性的)。

这里讲解下为什么zk数据发生变化时,只是把监听事件发给客户端,而不是带上最新修改数据一起发送通知给客户端。

  • 因为这样操作有利于节省带宽,**最新的数据可能客户端并不在意,**所以没什么必要把数据一起通知给客户端。
  • 因为zookeeper连接的节点可能会很多,zk除了要发送监听事件外,还要处理其他的客户端发送的命令,如**果发送监听事件还要带上数据,对zk的性能影响是非常大的。**最好的办法就是客户端收到监听事件,有需要再去拉取最新的数据。

zk还可以实现分布式锁等,这些实现方案无非都依赖zk的两点

文件系统+监听通知机制。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值