专栏首页码农知识点disconf相关问题总结-结合issue,官方文档

disconf相关问题总结-结合issue,官方文档

  • disconf-web创建最新配置时,只会把配置数据落到mysql,并不会马上把数据推到zk上,而需要监听该节点的disconf-client实例启动时,如果还没有创建zk节点,则由客户端创建节点并注册watch.所以启动流程中可能遇到的问题:

image.png

  • 配置文件类、配置项所在的类、回调函数类 都必须是JavaBean,并且它们的”scope” 都必须是singleton的。
  • 本系统实现的注解方案具有些局限性,具体如下:
    • 用户标注配置时略有些不习惯。目前注解是放在get方法之上的,而不是放在域上。
    • 注解放在get方法上,一般情况下是没有问题的。但是对于”call self”的方法调用,AOP无法拦截得到,这样就无法统一处理这些配置。一旦出现这种情况,“非一致性读问题”就会产生。
  • 配置“不一致性读“ 问题:应用系统的配置更新过程,它会涉及到多个配置项的更新,它不是一个原子过程。如果在配置更新的过程中,应用程序去读取配置,这里可能存在些“时间窗口”,从而导致不一致性读问题。

对于Web系统: 要实现统一读取,可以使用ThreadContext+AOP来实现。 ThreadContext的使用方式有以下几种:

解决方法一:提供ThreadContext包,在每次请求一开始时都复制系统里的所有配置缓存(复制过程要与配置更新Sync互斥),从而保证每次会话的数据的一致性。 解决方法二:提供ThreadContext包,每次请求都绑定一个版本号,如果读取时版本号不一致则报错,需要重新请求。 解决方法三:方法二的加强版,添加一个注解定义,标注它是需要强一制性的,每次会话读取时只复制这些强一制性配置(复制过程要与配置更新Sync互斥)。 解决方法四:提供ThreadContext包,系统内保存有多个配置缓存层,读取时统一读取某个版本的缓存。每当配置更新时,缓存层增加。 第一种方法,代价太大。第二种方法,严重增加用户负担,第三种还是需要用户关心这个事情。我们将采用第四种方法

对于非Web项目:

比较难解决非一致性读取的问题。因为它没有了会话这样一个概念。Apache的FileChangedReloadingStrategy Reload配置文件的方案也没有解决此问题。所以,我们打算放弃这方面的解决。但是,我们还是会提供一个简单却Ugly的解决方案:提供函数来标识用户读取配置的边界。用户可以放弃使用这个方案,但是我们不保证不会发生“不一致读’问题。

  • disconf-web的ZK异常处理 disconf-web可以完全保证在任何情况下,与ZK集群的自动连接。 服务启动前,zk连接不上:
  • 开始连接不上:
    • apache ZK client自身会自动(永久)去连接ZK server. 但是一直连接不上。
    • 因此,web上所有操作均会失败,抛大异常,请求失败,只会重试一次,不会重试多次
  • 后面突然连接上了:
    • apache ZK client 收到server SyncConnected消息。
    • 这时所有操作均成功
  • 后面又突然连接不上了:
    • apache ZK client 收到server Disconnected 消息。
    • 这时,apache ZK client自身会自动(永久)去连接ZK server. 但是一直连接不上。
    • 这时 web 上 所有操作均会失败,抛大异常,请求失败,只会重试一次,不会重试多次
  • 后面突然连接上了:
    • apache ZK client 收到server Expired 消息。
    • 这时表示会话丢失啦,apache ZK client 自动断开与Server的连接,表示此时让你来处理,因为它不知道应该如何处理。
    • 这时,disconf-core会reconnect zkserver,重新建立会话。
    • 成功后,apache ZK client 收到server SyncConnected 消息。表示连接成功
  • 后面又突然连接不上了:
    • apache ZK client 收到server Disconnected 消息。
    • 这时,apache ZK client自身会自动(永久)去连接ZK server. 但是一直连接不上。
    • 这时 web 上 所有操作均会失败,抛大异常,请求失败,只会重试一次,不会重试多次

服务启动前,zk连接上了:

  • 开始连接:
    • apache ZK client 收到server SyncConnected消息。
    • 这时所有操作均成功功
  • 后面又突然连接不上了…… (与上面分析一样,此不再赘述)

注意

ZK一般需要以集群的形式提供出来。假设有N台ZK,

  • 只要至少有一台ZK存活,disconf-web就可以正常工作。而且永远不会收到 server Expired 的消息。
  • 只要有一台ZK死亡,disconf-web就会收到 Disconnected 消息。但是系统仍可以继续工作。
  • 如果所有zk都死亡,那么disconf-web会收到 Disconnected 消息。只要有一台存活,disconf-web就会收到

** * disconf-client的ZK异常处理

disconf-client可以完全保证: 如果在启动程序时保证ZK集群是可用的,那么,就可以保证在任何情况下,与ZK集群的自动连接。

下面按情况进行分析:

程序启动前,zk连接不上

这时disconf-client无法在ZK上注册信息。这是必须禁止发生的情况。也是disconf-client无法支持的情况。

一旦发生这种情况,请先恢复ZK集群,再启动你的程序。

程序启动前,zk连接上了:

如果在程序启动过程中,ZK是正常的,那么,disconf-client可以保证与ZK连接的自动性。

  • 只要集群有一台还存活着,你的程序配置还是受disconf托管。
  • 如果集群所有机器均死亡,这时你的程序将游离于disconf之外。只要集群中有任何一台ZK机器重新开启,那么 你的程序将重新 由disconf进行托管。
 @Override
    public void process(WatchedEvent event) {

        //
        // 结点更新时
        //
        if (event.getType() == EventType.NodeDataChanged) {

            try {

                LOGGER.info("============GOT UPDATE EVENT " + event.toString() + ": (" + monitorPath + "," + keyName
                        + "," + disConfigTypeEnum.getModelName() + ")======================");

                // 调用回调函数, 回调函数里会重新进行监控
                callback();

            } catch (Exception e) {

                LOGGER.error("monitor node exception. " + monitorPath, e);
            }
        }

        //
        // 结点断开连接,这时不要进行处理,表示已经断开了和zk的连接
        //
        if (event.getState() == KeeperState.Disconnected) {

            if (!debug) {
                LOGGER.warn("============GOT Disconnected EVENT " + event.toString() + ": (" + monitorPath + ","
                        + keyName + "," + disConfigTypeEnum.getModelName() + ")======================");
            } else {
                LOGGER.debug("============DEBUG MODE: GOT Disconnected EVENT " + event.toString() + ": (" +
                        monitorPath +
                        "," +
                        keyName +
                        "," + disConfigTypeEnum.getModelName() + ")======================");
            }
        }

        //
        // session expired,需要重新关注哦
        //
        if (event.getState() == KeeperState.Expired) {

            if (!debug) {

                LOGGER.error("============GOT Expired  " + event.toString() + ": (" + monitorPath + "," + keyName
                        + "," + disConfigTypeEnum.getModelName() + ")======================");

                // 重新连接
                ZookeeperMgr.getInstance().reconnect();

                callback();
            } else {
                LOGGER.debug("============DEBUG MODE: GOT Expired  " + event.toString() + ": (" + monitorPath + ","
                        + "" + keyName + "," + disConfigTypeEnum.getModelName() + ")======================");
            }
        }
    }

注意 disconf-client必须保证在程序在启动时,ZK集群的可用性。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • disconf客户端使用篇

    此时,当更新disconf-web管理台对应的remote.properties文件时,会重新在disconf/config目录下下载最新文件,RemoteSe...

    Monica2333
  • disconf配置crud交互流程

    整体的实现是用zk watch作为轻量级的实时推送。当配置更新时, disconf-web推送最新配置到zk上,disconf-client获取到zk事件通知时...

    Monica2333
  • disconf-client原理分析

    com.baidu.disconf.client.DisconfMgrBean:第一个加载的bean

    Monica2333
  • 第3课 惊天秘诀,2位账号如JD只要0.5个EOS就可注册?!

    【本文目标】 通过本文学习,可以抢注12位以下的EOS心意账号,便于后续增值和使用。 【前置条件】 本文无技术前置条件,操作及其简单,但是需要有EOS代币...

    辉哥
  • Python实现链表

    py3study
  • 用最容易的方式学会单链表(Python实现)

    在本博客中,我们介绍单链表这种数据结构,链表结构为基于数组的序列提供了另一种选择(例如Python列表)。

    宇宙之一粟
  • Kubernetes 中的 DNS 查询

    在 Kubernetes 中部署应用的主要优势之一就是可以做到无缝的应用发现。Service 的概念使群集内通信变得容易,Service 代表了支持一组 Pod...

    我是阳明
  • 如何在Spectrum公链上开发Dapp?

    Spectrum光谱链是由Ethereum以太坊的链发展而来,所以是完全兼容以太坊。 但是又有不同,主要是共识机制不同,二级架构layer2不同,更加兼容移动...

    rectinajh
  • 树莓派搭建自用去广告DNS

    DNS,英文全称「Domain Name Server」,域名系统(服务)协议(DNS)是一种分布式网络目录服务,主要用于域名与 IP 地址的相互转换,以及控制...

    卜露
  • 智能合约编写之 Solidity 的设计模式

    区块链所具有的独特优势,例如,数据公开透明、不可篡改,可以为业务带来便利。但与此同时,也存在一些隐患。数据的公开透明,意味着任何人都可以读取;不可篡改,意味着信...

    区块链大本营

扫码关注云+社区

领取腾讯云代金券