问题的提出
在微服务架构下,每个业务模块都分解到了不同的微服务(*-provider)上,同时业务模块还提供了对外的API接口(*-rest项目)。这样在开发、测试和生产环境中,分布了大量的jar包。而每个jar包都包含了许多配置,包括并不限于
- 连接数据库、zookeeper、redis的信息;
- 日志、API文档的配置;
- 业务中使用的动态变量配置等。
现在的使用方式是在yml定义这些配置,并在启动脚本中更新成符合当前环境的配置,但存在如下问题:
- 存在多个配置文件,管理混乱和易出错;
- 修改某个配置时需要重新编译打包(开发时)或重启线上服务器 (项目集群时,更加令人崩溃) ;
- 不能做到配置信息的保密,例如数据库连接字符串中的敏感信息;
- 不同环境上线包不一致: 例如JDBC连接, 不同环境需要差异化配置;
- 配置项重复,明明一个东西,用好几种配置项来表示。
由于存在这些问题,所以急需引入分布式配置管理平台,提供统一的配置管理服务。
目标
通过引入分布式配置管理平台,达到如下的目标:
- 按项目(项目A、项目B...)和环境(local、测试、线上...)集中管理配置项,而不是管理配置文件;
- 本地做到无配置文件化(除了平台的配置),全部从统一的配置管理平台下载;
- 线上配置项对开发和无关人员隐藏;
- 配置更新不用重启或重新部署;
- 项目内配置项不重复,项目间尽量不重复。
产品选型
主评估产品
解决方案
主流的分布式配置管理平台是一套服务器-客户端的web应用程序。服务器端负责连接数据库存储所有的配置项,并由配套UI供用户管理这些配置项;客户端为支持该管理平台的具体业务项目,可以接收服务器下发的配置项。整个体系通过ZooKeeper进行协调,可实现配置变更的推送。
产品介绍
disconf是百度推出的分布式配置管理平台,原理描述如上。特点是知名用户较多,github上的更新几乎停止(也可能是比较稳定),官方文档很清楚,网上其他文档基本都是分发,就不列举了。
材料汇总:
- github地址:https://github.com/knightliao/disconf
- 文档地址:http://disconf.readthedocs.io/zh_CN/latest/
- springboot集成(客户端):https://my.oschina.net/u/3768341/blog/1615001
其它同类产品
同类产品的原理基本相同,包括并不限于
-
diamond: 阿里的产品,貌似没有开源,和disconf比较,网上有一个列表。
xxl-conf: 做了实际评估,服务器端没有问题,客户端和现有框架有冲突,启动失败;
jeesuit-config: 未做实际评估
dictator: 项目用户太少,偏向个人项目
对比依据及结论
重点评估了disconf和xxl-conf,diamond做简单了解,从使用门槛,用户数量,更新程度等多方面评估,还是主要评估disconf是否可以继续使用,其它备选方案暂时放弃。
产品评估详细过程
安装
disconf-web
基本安装步骤参考官网说明,web就是服务器端,实际需要tomcat支持,未做成SpringBoot启动模式,但支持前后端分离,具体需要关注的地方包括
- 拷贝若干配置文件到特定目录,并按实际修改
- 环境变量设置按实际情况
- tomcat的server.xml文件修改
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<Context path="" docBase="/Users/zhaoyan/Documents/Personal/Tech/data/disconf-rd/war"></Context>
</Host>
- 403问题(nginx无权限访问index.html),原因是路径上有的目录root访问不了,全路径改为777即可。
- 上传配置文件报错问题,web编译后可能缺少一个apollo-1.0.14.jar(检查WEB-INF/lib目录,如果没有就手工拷贝一个)
- 配置无法下载的问题,zookeeper的版本和线上不一致。根据zk的版本,调整pom中的zk引用版本号,再次编译web项目即可实现引入。
disconf-client
由于业务项目全部采用SpringBoot,故根据以上文档做集成,具体需要关注的地方包括
- 更新DisConf类中的扫描路径
- 找不到类
java.lang.NoClassDefFoundError: com/baidu/disconf/core/common/utils/ClassLoaderUtil
pom里显式的增加core包的定义 - reflection包冲突
java.lang.NoSuchMethodError: org.reflections.util.FilterBuilder.includePackage(Ljava/lang/String;)Lorg/reflections/util/FilterBuilder;
swagger里用的reflection版本过高,手动引入0.9.9-RC1,在spring-boot-starter-swagger里设置exclude - 为了使用disconf的托管模式,需要定义配置文件下载的模式(定义两个bean),所以在DisConf中加入如下代码
@Bean
public ReloadablePropertiesFactoryBean getConfigproperties_disconf(){
ReloadablePropertiesFactoryBean bean = new ReloadablePropertiesFactoryBean();
List<String> ymlFiles = new LinkedList<>();
ymlFiles.add("classpath:/application.yml");
ymlFiles.add("classpath:/application-dev.yml");
bean.setLocations(ymlFiles);
return bean;
}
@Bean
public ReloadingPropertyPlaceholderConfigurer getPropertyConfigurer(){
ReloadingPropertyPlaceholderConfigurer configurer = new ReloadingPropertyPlaceholderConfigurer();
configurer.setIgnoreResourceNotFound(true);
configurer.setIgnoreUnresolvablePlaceholders(true);
try {
configurer.setPropertiesArray(new Properties[]{getConfigproperties_disconf().getObject()});
} catch (IOException e) {
e.printStackTrace();
}
return configurer;
}
试用
服务器端
服务器端的功能主要在于管理配置,disconf提供了几个维度来管理这些配置项
- 项目:即一个微服务模块或API接口(rest)
- 环境:系统内置四种环境:rd(研发),qa(测试),local(uat?),online(生产)
- 版本:目前只支持x_x_x_x这种格式
另外配置也有两种,分别是
- 配置项:配置项可以单独创建并被客户端感知,特别是支持自动更新;
- 配置文件:专用于托管模式,即只改为集中管理配置文件,客户端自动下载,而不动内部的配置项。这样做的最大好处是不必修改现有代码(对于一些特殊配置,修改也是不太可能,就像IAC),减少了工作量。
客户端
客户端有两种使用方式:
对于普通配置项,可以使用@DisconfItem(key="真正的key")
注解到getXXX方法。disconf一个不太理想的地方就是不能像@value一样注解到变量上。
对于大量的系统中的配置项,由于内容多,也不能逐一修改代码,所以必须采用托管模式,实测把yml文件上传到集中管理后,删除本地配置文件,启动是没有问题的,说明此模式生效。
测试
暂无
相关人员评审结果
实际评估人
disconf从搭建入门来看比较简单,尽管服务器端没有做SpringBoot封装,但总体来说用tomcat还可以接受。从功能上讲,能够达到统一配置,配置更新等作用,能够解决报告开始提到的问题。有几个需要改进和深入研究的问题:
- 不能注解到变量上,从发展上看应该不会做改进了,所以使用习惯上要改;
- jar包里的代码使用@value,不能生效,貌似代码内部本身的没有问题,最典型的就是ClientSessionDao里的iacLogUrl,dal里的HttpConf.IAC_REST_HOST也是不行,这是目前遇到的最大障碍;
- 一些资源配置要往配置项过渡,从配置文件中独立出来,否则上线后还是不方便。同时就必须修改类似DubboConf,DatasourceConf这种文件,手工的处理配置;
- 为了最大限度的提升效果,运维团队应该整理出一套使用规范。
开发团队
- Required: false
- Description: 如果需要的话
产品团队
- Required: false
- Description: 如果需要的话
运维团队
- Required: false
- Description: 如果需要的话
公司管理层
- Required: false
- Description: 如果需要的话
注:除实际评估人外,其它四个团队最少有一个要提出评审意见
最终结论
是否引入到公司产品体系的最终结论
- Required: true
- Description:
- 是否应用该被评估产品
- 应用后能否解决现有问题,能否达到预设目标
实施计划
- Required: true
- Description: 包括并不限于实施进程、实施结果和参与人等。