源码地址:https://github.com/qkbao/Disconf.Net
作者:青客宝 联系qq:后续奉上
为了更好的解决分布式环境下多台服务实例的配置统一管理问题,本文提出了一套完整的分布式配置管理解决方案。结合.net项目具体情况,实现了配置发布的统一化,对配置进行持久化管理并对外提供restful接口,在此基础上,基于ZooKeeper实现对配置更改的实时推送。系统参考了百度的Disconf,实现和改进了部分功能,是Disconf的.Net精简版,功能有待进一步完善。
1.系统设计
1.1设计理念
l 简单易用,用户体验良好
l 支持配置(KV配置项+配置文件)的分布式化管理
l 配置发布、更新统一化:用户统一在平台上进行发布、更新配置。
l 配置更新自动化:用户在平台更新配置,使用该配置的系统会自动发现该情况,并应用新配置。
系统结构图如下:
初始化时,业务流程图如下:
配置更新时,业务流程图如下:
1.2.功能介绍
系统模块架构图如下:
1.2.1Client
配置管理模块:统一管理用户实例中本地配置文件和配置项
下载模块:restful风格的下载配置文件和配置项
watch模块:监控远程配置文件和配置项的变化
1.2.2Web
配置管理模块:支持配置模板(配置项或配置文件)的上传、下载、更新
配置存储模块:管理所有配置的存储和读取,根据appName、version、environment来区分项目配置
通知模块:当配置更新后,实时通知使用这些配置的所有实例
权限控制:web用户的权限控制
2.客户端应用
2.1添加clientConfig配置节点
在app.config或者web.config中的configSections节点下添加配置
<section name=”clientConfig” type=”Disconf.Net.Client.ClientConfigSection,Disconf.Net.Client”/>
然后在appSettings同级别的节点上添加clientConfig配置,示例如下
<configSections> <section name=”clientConfig” type=”Disconf.Net.Client.ClientConfigSection,Disconf.Net.Client”/> </configSections> <appSettings file=”appSettings.config”/> <clientConfig configSource=”clientConfig.config”/>
2.2clientConfig配置说明
具体示例如下:
<clientConfig webApiHost=”http://192.168.1.100:8088/” enableRemote=”true”> <clientInfo appName=”consoletest” environment=”Dev” version=”1.0.0.0” clientName=”Console_1”/> <updateStrategy fileIgnores="notdown.txt" itemIgnores="aa,bb,cc " startedSync="true" retryTimes="3" retryIntervalSeconds="10" /> <preservation absolutePath="false" tmpRootDirectory="Tmp\Download\Configs" factRootDirectory="" tmpItemsLocalName="~items.xml" tmpFilesLocalName="~files.txt"/> </clientConfig>
节点名称 |
必配 |
默认值 |
节点描述 |
|
webApiHost |
|
Y |
|
Rest服务器域名地址 |
enableRemote |
|
N |
true |
是否启用远程配置,默认true,设为false的话表示不从远程服务器下载配置 |
clientInfo |
appName |
Y |
|
客户端程序名称,注意大小写要与服务端一致 |
environment |
Y |
|
当前客户端程序所处环境,注意大小写要与服务端一致 |
|
version |
Y |
|
当前客户端程序版本,注意大小写要与服务端一致 |
|
clientName |
N |
|
客户端标识,用于服务端查看已更新客户端,如果不设置则默认获取客户端电脑名称 |
|
updateStrategy |
fileIgnores |
N |
|
要忽略更新的文件配置,以,分割,注意大小写要与服务端一致 |
itemIgnores |
N |
|
要忽略更新的键值对配置,以,分割,注意大小写要与服务端一致 |
|
startedSync |
N |
true |
启动时是否同步加载,默认同步 |
|
retryTimes |
N |
3 |
当获取失败时的重试次数 |
|
retryIntervalSeconds |
N |
10 |
每次重试时间间隔,单位秒 |
|
preservation |
absolutePath |
N |
false |
是否绝对路径,默认false。当false时,表示默认以 AppDomain.CurrentDomain.BaseDirectory为比较点,注意:该配置同时适用于TmpRootDirectory、 FactRootDirectory,即要么都只能绝对路径,要么都只能相对路径 |
tmpRootDirectory |
N |
Tmp/Download/Configs |
下载下来的配置临时保存文件夹根目录 |
|
factRootDirectory |
N |
Configs |
配置文件实际所在的根目录 |
|
tmpItemsLocalName |
N |
~items.xml |
在临时目录下用于保存所有键值对的文件名,设置为空表示不保存,文件保存在TmpRootDirectory目录下,所以注意不要与 实际配置文件名字冲突 |
|
|
tmpFilesLocalName |
N |
~files.txt |
在临时目录下用于保存所有文件配置名的文件名,设置为空表示不保存,文件保存在TmpRootDirectory目录下,所以注意不要与实际配置文件名字冲突 |
2.3Rules
除了配置外,还需要设置更新策略,客户端才能进行配置更新。目前,Rules设置仅支持编码的方式进行,Rule分两种:FileRule,ItemRule,下面分别进行描述:
FileRule:用于设置如何更新文件类型配置,其包含以下方法
方法名 |
描述 |
IFileRule MapTo(string refreshSectionName) |
注册Rule规则,设置默认的文件配置映射 参数refreshSectionName表示更新回调时, ConfigurationManager.RefreshSection要刷新的节点名称,默认采用远程配置的configName |
IFileRule RefreshIgnores() |
不自动调用ConfigurationManager.RefreshSection方法更新配置 |
IFileRule CallBack(Action action) |
当文件下载完成并且替换本地对应文件后回调,注意此处将采用委托链的方式,即多次调用均会被执行 |
ItemRule:用于设置如何更新键值对类型配置,其包含以下方法
方法名 |
描述 |
IItemRule MapTo(string propName) |
注册Rule规则,设置默认的属性映射参数 propName表示要赋值的属性名,默认采用远程的configName |
IItemRule SetProperty<T>(T entity, string propName = null, Func<string, object> typeConvert = null) |
更新指定实体的属性值,按默认方式获取实例属性,注意此处多次调用均会被执行 |
IItemRule SetProperty(object entity, PropertyInfo prop, Func<string, object> typeConvert = null) |
更新指定实体的属性值,注意此处多次调用均会被执行 |
IItemRule SetStaticProperty<T>(string propName = null, Func<string, object> typeConvert = null) |
更新静态属性的值,按默认方式获取静态属性,注意此处多次调用均会被执行 |
IItemRule SetStaticProperty(PropertyInfo prop, Func<string, object> typeConvert = null) |
更新静态属性的值,注意此处多次调用均会被执行 |
IItemRule CallBack(Action<string> action) |
当值发生变更时如何进行回调,注意此处将采用委托链的方式,即多次调用均会被执行 |
2.4ConfigManager
该类为Client配置入口,通过Singleton提供唯一实例,除了提供Rules的配置入口外,还提供异常通知的事件
要使Disconf.Net.Client工作,必须显示执行指定方法manager.Init(),而在init之前,还需设置Rule和Fault,可以通过ConfigManager.Instance来获取该类的实例对象,然后通过对应的Rule进行相关Rule设定,示例如下:
//要更新的文件 ConfigManager.Instance.FileRules.For("appSettings.config").CallBack(() => { Console.WriteLine("File changed notice twice"); }); //要更新的键值对 ConfigManager.Instance.ItemRules.For("Dai").MapTo("Person").SetStaticProperty<Program>().CallBack(v =>{ Console.WriteLine("Now item value:{0}", v); Console.WriteLine("Program.Person is {0} now", Program.Person); if (v.Length > 3) { throw new Exception("Too Long"); } }); //忽略更新到本地的键值对 ConfigManager.Instance.ItemRules.For("Peng").CallBack(v =>{ Console.WriteLine("Now item value:{0}", v); }); //异常处理 ConfigManager.Instance.Faulted+=Manager_Faulted; //Config初始化,包括ZooKeeper、scan等 ConfigManager.Instance.Init();
需要特别说明的是:
1、File因为属于下载后覆盖指定位置文件的方式,所以对于Rule可以设置默认规则,如例子中的appSettings.config,其对应的就是config文件中的appSettings部分,此时如果不需要进行CallBack调用,且文件名称(去除后缀)部分与Section一致,那么这部分Rule设置可以忽略,程序会在初始化时自动进行默认设置,而对于Item,因为无法确认更新策略,所以如果不设置Rule,那么就算从服务端获取到了值,该部分也只能被忽略。
2、对于异常部分,程序只是简单的通过Faulted事件来传递异常信息,该事件只有一个Exception类型的参数。
3.web端应用
配置步骤:
1、 创建具体应用(项目)
2、 创建应用的配置模板(1~n个配置,如appSetting.config、redisconfig.config、rabbitMQConfig.config等配置模板)
3、 创建应用的环境(如:开发环境、测试环境、仿真环境等),修改相关的配置
4、 启用对应的配置
5、 至此,client端就可以获取应用环境对应的所有配置
3.1登录
登陆进入配置管理界面
3.2应用
【新建】:填写应用名称,应用描述保存完成新建,返回可返回应用管理首页。
【初始化ZooKeeper】:第一次启动时Zookeeper初始化。
【编辑】:与新建界面一致,可修改应用名称,应用描述,保存即返回应用管理首页。
【编辑环境】:进入环境环境配置管理首页。
【删除】:删除对应应用记录。
3.3模板
显示所有模板,操作环境配置前,需要先配置模板,根据模板对相应环境的配置进行操作。
【新建】:新增模板,填写模板名称、描述、类型、默认值版本号等,如选择文件类型。可上传文件读取文件内容,版本号可以选择已经有的版本号,或者新建版本号。
【编辑】:操作同新建模板,可对模板内容进行修改。
【删除】:点击删除可删除对应模板记录,如该模板在环境中存在配置项,则该模板不允许删除,需删除对应该模板的配置项,才可以删除对应模板。
3.4环境
【新增环境】点击加号可以新增环境,填写环境名称,描述保存即可。
【编辑环境】在对应环境上点击鼠标右键即可弹出编辑菜单,点击Edit即可编辑环境,可以修改名称内容等。
【配置首页】:配置首页根据版本进行分类,默认显示头部第一个版本,点击其他版本可以进行切换,显示的配置项是模板默认配置项,点击启用即可个性化赋值,针对不同环境进行不同的赋值。编辑可编辑相应配置,禁用等同于删除配置。
【启用配置】:名称默认值不能修改,可以点击使用默认值,直接赋值,也可以上传文件使用文件内容,保存即可。
【编辑配置】:操作同启用配置,保存即可修改值。
【禁用配置】:禁用等同于删除配置,删除对应模板配置项,可删除对应模板。
3.5角色
【角色首页】:
Ø 角色首页展示角色列表,角色分为超级管理员和非超级管理员;
Ø 超级管理员角色不展示;
Ø 超级管理员可以看到所有非超级管理员角色,非超级管理员只可以看到当前角色用户创建的角色;
Ø 可以新增角色,也可以对角色进行编辑,只有在创建用户时勾选是否为系统管理员才可以进行角色管理。
【新建角色】:
Ø 新建角色输入角色名称,可以勾选的权限为当前用户所拥有的权限;
Ø 新建的角色作为该用户的下属角色,可分配给当前用户新建的用户;
Ø 父级权限为新建应用所增加的权限,以后每增加一个环境,就相应的增加该应用下的该环境权限,除超级管理员外的角色需对应勾选该权限才能看到该应用或者该权限,保存角色即可。
【编辑角色】:操作同新建角色,可以对该角色进行名称修改,权限修改。
3.6用户
管理用户首页,显示所有用户,可进行新建,编辑用户等操作。
【新建用户】:填写姓名,用户名,密码,选择角色(拥有对应角色权限、且可以选择的角色为当前登陆用户新建的角色),选择是否为系统管理员(系统管理员拥有新建用户、新建角色权限),保存即可。
【编辑用户】:操作同新建用户,保存即可修改。