NameServer模塊閱讀2:KVConfigManager

摘要

本節(jié)講解順序如下

KVConfigManager作用
字段
  lock 讀寫鎖
  configTable 內(nèi)存記錄的配置
方法
  構(gòu)造函數(shù)
  load:加載配置文件,讀取到內(nèi)存的configTable中
  putKVConfig:添加一條記錄
  deleteKVConfig:刪除一條記錄
  persist:將內(nèi)存記錄的configTable持久化到配置文件
  getKVListByNamespace:拿到configTable對(duì)應(yīng)namespace的所有記錄
  getKVConfig:獲取configTable中namespace,key對(duì)應(yīng)的一條記錄
  printAllPeriodically:打印configTable所有配置,被周期性的調(diào)用
思考
refer

說(shuō)明

KVConfigManager作用是

加載namesrvController指定的kvConfig配置文件(常為xxx/kvConfig.json)到內(nèi)存
讀取或增加,刪除kvConfig記錄
將內(nèi)存記錄的配置,持久化到文件
打印所有kvConfig配置

字段

    private static final Logger log = LoggerFactory.getLogger(LoggerName.NAMESRV_LOGGER_NAME);

    private final NamesrvController namesrvController;//NameServer控制類

    private final ReadWriteLock lock = new ReentrantReadWriteLock();//讀寫鎖
    private final HashMap<String/* Namespace */, HashMap<String/* Key */, String/* Value */>> configTable =
        new HashMap<String, HashMap<String, String>>();

主要注意

lock 是一個(gè)讀寫鎖,用來(lái)控制并發(fā)
configTable 就是在內(nèi)存中記錄住的kv配置,第一級(jí)key為NameSpace(暫時(shí)什么用還不清楚)

方法

構(gòu)造函數(shù)

    public KVConfigManager(NamesrvController namesrvController) {
        this.namesrvController = namesrvController;
    }

傳入一個(gè)NamesrvController,目的是為了后面獲取到kvConfig的配置路徑

load

加載配置文件,讀取到內(nèi)存的configTable中

源碼如下

    public void load() {
        String content = null;
        try {
            //解析kvConfigPath,默認(rèn)為NamesrvConfig.kvConfigPath(../kvConfig.json),解析文件,得到內(nèi)容,賦給content
            content = MixAll.file2String(this.namesrvController.getNamesrvConfig().getKvConfigPath());
        } catch (IOException e) {
            log.warn("Load KV config table exception", e);
        }
        if (content != null) {
            KVConfigSerializeWrapper kvConfigSerializeWrapper =
                KVConfigSerializeWrapper.fromJson(content, KVConfigSerializeWrapper.class);//根據(jù)json的文本內(nèi)容解析得到KVConfigSerializeWrapper對(duì)象
            if (null != kvConfigSerializeWrapper) {
                this.configTable.putAll(kvConfigSerializeWrapper.getConfigTable());//存入configTable
                log.info("load KV config table OK");
            }
        }
    }

步驟就是

根據(jù)kvConfigPath得到文件內(nèi)容
以json格式解析得到KVConfigSerializeWrapper對(duì)象

放入configTable屬性中

putKVConfig

添加一條記錄

源碼如下

    public void putKVConfig(final String namespace, final String key, final String value) {
        try {
            this.lock.writeLock().lockInterruptibly();
            try {
                HashMap<String, String> kvTable = this.configTable.get(namespace);
                if (null == kvTable) {
                    kvTable = new HashMap<String, String>();
                    this.configTable.put(namespace, kvTable);
                    log.info("putKVConfig create new Namespace {}", namespace);
                }

                final String prev = kvTable.put(key, value);
                if (null != prev) {//有舊的key,更新
                    log.info("putKVConfig update config item, Namespace: {} Key: {} Value: {}",
                        namespace, key, value);
                } else {//沒(méi)有,創(chuàng)建新的
                    log.info("putKVConfig create new config item, Namespace: {} Key: {} Value: {}",
                        namespace, key, value);
                }
            } finally {
                this.lock.writeLock().unlock();
            }
        } catch (InterruptedException e) {
            log.error("putKVConfig InterruptedException", e);
        }

        this.persist();//持久化到文件
    }

步驟就是

放入configTable中,namespace對(duì)應(yīng)一級(jí)key,key對(duì)應(yīng)二級(jí)
然后將configTable進(jìn)行持久化到文件

deleteKVConfig

刪除一條記錄

源碼如下

    public void deleteKVConfig(final String namespace, final String key) {
        try {
            this.lock.writeLock().lockInterruptibly();
            try {
                HashMap<String, String> kvTable = this.configTable.get(namespace);
                if (null != kvTable) {
                    String value = kvTable.remove(key);
                    log.info("deleteKVConfig delete a config item, Namespace: {} Key: {} Value: {}",
                        namespace, key, value);
                }
            } finally {
                this.lock.writeLock().unlock();
            }
        } catch (InterruptedException e) {
            log.error("deleteKVConfig InterruptedException", e);
        }

        this.persist();//持久化到文件
    }

步驟就是

從configTable刪除對(duì)應(yīng)記錄
然后將configTable持久化到文件

persist

將內(nèi)存記錄的configTable持久化到配置文件

源碼如下

    public void persist() {
        try {
            this.lock.readLock().lockInterruptibly();
            try {
                //把configTable放入KVConfigSerializeWrapper
                KVConfigSerializeWrapper kvConfigSerializeWrapper = new KVConfigSerializeWrapper();
                kvConfigSerializeWrapper.setConfigTable(this.configTable);
                //把KVConfigSerializeWrapper轉(zhuǎn)成json串
                String content = kvConfigSerializeWrapper.toJson();

                if (null != content) {
                    //把內(nèi)容寫入 kvConfig的文件
                    MixAll.string2File(content, this.namesrvController.getNamesrvConfig().getKvConfigPath());
                }
            } catch (IOException e) {
                log.error("persist kvconfig Exception, "
                    + this.namesrvController.getNamesrvConfig().getKvConfigPath(), e);
            } finally {
                this.lock.readLock().unlock();
            }
        } catch (InterruptedException e) {
            log.error("persist InterruptedException", e);
        }

    }

步驟就是

1.把configTable放入KVConfigSerializeWrapper
2.把KVConfigSerializeWrapper轉(zhuǎn)成json串
3.把json串寫入kvConfig文件

getKVListByNamespace

拿到configTable對(duì)應(yīng)namespace的所有記錄

源碼如下

    /**
     * 拿到configTable對(duì)應(yīng)namespace的所有記錄,
     * 返回encode得到的byte[]
     */
    public byte[] getKVListByNamespace(final String namespace) {
        try {
            this.lock.readLock().lockInterruptibly();
            try {
                HashMap<String, String> kvTable = this.configTable.get(namespace);
                if (null != kvTable) {
                    KVTable table = new KVTable();
                    table.setTable(kvTable);
                    return table.encode();
                }
            } finally {
                this.lock.readLock().unlock();
            }
        } catch (InterruptedException e) {
            log.error("getKVListByNamespace InterruptedException", e);
        }

        return null;
    }

getKVConfig

獲取configTable中namespace,key對(duì)應(yīng)的一條記錄
源碼如下

    public String getKVConfig(final String namespace, final String key) {
        try {
            this.lock.readLock().lockInterruptibly();
            try {
                HashMap<String, String> kvTable = this.configTable.get(namespace);
                if (null != kvTable) {
                    return kvTable.get(key);
                }
            } finally {
                this.lock.readLock().unlock();
            }
        } catch (InterruptedException e) {
            log.error("getKVConfig InterruptedException", e);
        }

        return null;
    }

printAllPeriodically

打印configTable所有配置,被周期性的調(diào)用

源碼如下

public void printAllPeriodically() {
        try {
            this.lock.readLock().lockInterruptibly();
            try {
                log.info("--------------------------------------------------------");

                {
                    log.info("configTable SIZE: {}", this.configTable.size());
                    Iterator<Entry<String, HashMap<String, String>>> it =
                        this.configTable.entrySet().iterator();
                    while (it.hasNext()) {//一級(jí)key
                        Entry<String, HashMap<String, String>> next = it.next();
                        Iterator<Entry<String, String>> itSub = next.getValue().entrySet().iterator();
                        while (itSub.hasNext()) {//二級(jí)key
                            Entry<String, String> nextSub = itSub.next();
                            log.info("configTable NS: {} Key: {} Value: {}", next.getKey(), nextSub.getKey(),
                                nextSub.getValue());
                        }
                    }
                }
            } finally {
                this.lock.readLock().unlock();
            }
        } catch (InterruptedException e) {
            log.error("printAllPeriodically InterruptedException", e);
        }
    }

思考

注意lock的使用

在各方法中適宜的調(diào)用讀鎖和寫鎖

問(wèn)題

NameSpace有什么用?

只知道是一個(gè)區(qū)分的一級(jí)key

refer

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,694評(píng)論 19 139
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 47,285評(píng)論 6 342
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,323評(píng)論 25 708
  • 某一天,因?yàn)樘鞖鈩倓偤茫ê美?,我承認(rèn)是因?yàn)樽鳂I(yè)沒(méi)寫完,第二天就要交啦),我去了自習(xí)室,剛坐下,就看到了我的左前方...
    周三歲zq閱讀 307評(píng)論 0 0
  • 我在寫這篇文章的時(shí)候時(shí)間是凌晨三點(diǎn)。那時(shí)的我竟毫無(wú)困意可言,反而還他媽的有股子說(shuō)不清是什么緣由的興奮勁兒。 這種感...
    曹帽子閱讀 529評(píng)論 0 1

友情鏈接更多精彩內(nèi)容