NameServer模块阅读2:KVConfigManager

摘要

本节讲解顺序如下

KVConfigManager作用
字段
  lock 读写锁
  configTable 内存记录的配置
方法
  构造函数
  load:加载配置文件,读取到内存的configTable中
  putKVConfig:添加一条记录
  deleteKVConfig:删除一条记录
  persist:将内存记录的configTable持久化到配置文件
  getKVListByNamespace:拿到configTable对应namespace的所有记录
  getKVConfig:获取configTable中namespace,key对应的一条记录
  printAllPeriodically:打印configTable所有配置,被周期性的调用
思考
refer

说明

KVConfigManager作用是

加载namesrvController指定的kvConfig配置文件(常为xxx/kvConfig.json)到内存
读取或增加,删除kvConfig记录
将内存记录的配置,持久化到文件
打印所有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 是一个读写锁,用来控制并发
configTable 就是在内存中记录住的kv配置,第一级key为NameSpace(暂时什么用还不清楚)

方法

构造函数

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

传入一个NamesrvController,目的是为了后面获取到kvConfig的配置路径

load

加载配置文件,读取到内存的configTable中

源码如下

    public void load() {
        String content = null;
        try {
            //解析kvConfigPath,默认为NamesrvConfig.kvConfigPath(../kvConfig.json),解析文件,得到内容,赋给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);//根据json的文本内容解析得到KVConfigSerializeWrapper对象
            if (null != kvConfigSerializeWrapper) {
                this.configTable.putAll(kvConfigSerializeWrapper.getConfigTable());//存入configTable
                log.info("load KV config table OK");
            }
        }
    }

步骤就是

根据kvConfigPath得到文件内容
以json格式解析得到KVConfigSerializeWrapper对象

放入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 {//没有,创建新的
                    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对应一级key,key对应二级
然后将configTable进行持久化到文件

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删除对应记录
然后将configTable持久化到文件

persist

将内存记录的configTable持久化到配置文件

源码如下

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

                if (null != content) {
                    //把内容写入 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转成json串
3.把json串写入kvConfig文件

getKVListByNamespace

拿到configTable对应namespace的所有记录

源码如下

    /**
     * 拿到configTable对应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对应的一条记录
源码如下

    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所有配置,被周期性的调用

源码如下

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()) {//一级key
                        Entry<String, HashMap<String, String>> next = it.next();
                        Iterator<Entry<String, String>> itSub = next.getValue().entrySet().iterator();
                        while (itSub.hasNext()) {//二级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的使用

在各方法中适宜的调用读锁和写锁

问题

NameSpace有什么用?

只知道是一个区分的一级key

refer

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 136,212评论 19 139
  • Spring Boot 参考指南 介绍 转载自:https://www.gitbook.com/book/qbgb...
    毛宇鹏阅读 47,172评论 6 342
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 176,711评论 25 709
  • 某一天,因为天气刚刚好,(好啦,我承认是因为作业没写完,第二天就要交啦),我去了自习室,刚坐下,就看到了我的左前方...
    周三岁zq阅读 1,895评论 0 0
  • 我在写这篇文章的时候时间是凌晨三点。那时的我竟毫无困意可言,反而还他妈的有股子说不清是什么缘由的兴奋劲儿。 这种感...
    曹帽子阅读 3,290评论 0 1

友情链接更多精彩内容