简介
本文介绍一种基于protobuf实现的配置文件体系,提升配置文件使用体验,同时支持分环境加载不同配置。
本配置系统相对于json,支持配置中添加注释,方便理解;支持自动反序列化,操作简单,同时减少DOM操作不当造成的coredump。
本配置系统相对于yml等配置文件,支持自动反序列化;不会因为缩进问题造成解析失败。
使用说明
基础使用
基础使用的步骤包括proto定义、配置文件编写、服务引入三个环节。
首先是proto定义,参考下面定义一个proto:
| 1 | syntax="proto3"; | 
接着是服务配置编写,例如:
| 1 | port : 8080 | 
接着是在服务中使用了,由于本配置体系依赖了protobuf、glog、gflags,使用时确保链接这三个库。
使用代码如下:
| 1 | 
 | 
其中配置路径不需要后缀,默认配置文件后缀为”*.conf”,也就是”../conf/server.conf”文件。
ServerConfig为目标配置反序列化之后的对象。
高级使用
这部分介绍用户可以根据自己的需要,针对不同环境使用不同的配置,例如prod、pre、test使用不同的配置文件,同时有一份基准配置,优先使用指定环境的配置,如果该配置未设置,使用基准配置覆盖。
使用gflag “env”确定加载哪份配置作为环境配置,默认是prod。
使用gflag “suffix”确定配置文件后缀,默认是”conf”。
例如,基准配置conf/server.conf是:
| 1 | port : 8080 | 
环境配置conf/server-prod.conf是:
| 1 | port : 80 | 
最终得到的合并配置为:
| 1 | port: 80 | 
需要注意的是,如果一个字段是repeated时,如果环境配置没有设置,就使用基准配置的;如果环境配置设置了,就不会使用基准配置了。
实现原理
文本配置解析
基于protobuf的文本配置,利用的是google/protobuf/text_format.h文件中的google::protobuf::TextFormat::Parse函数,其功能是将文本内容反序列化为message内容。
这个函数其实是google::protobuf::Message的DebugString函数的逆操作。
解析的代码如下:
| 1 | int file = open(path.c_str(), O_RDONLY); | 
配置合并
protobuf提供了MergeFrom函数支持两个Message对象进行合并,对于repeated的结构,合并后的结果是这两个结构的并集。
这个情况是不符合预期的,例如Message里有a字段是repeated的,合并结果如下:
| A 配置中a字段元素数量 | B配置中a字段元素数量 | 合并结果 | 
|---|---|---|
| 2 | 0 | 2(全部来自A) | 
| 0 | 2 | 2(全部来自B) | 
| 2 | 3 | 2(全部来自A) | 
针对这样的需求,不能直接使用MergeFrom函数,需要使用protobuf的反射能力进行逐一赋值。
代码有点长,可以参考代码。