前言
随着项目的微服务化以及多环境开发部署,固定的参数配置早已不能满足多变的业务需求或者项目中个性化的信息配置,大势所趋下,实时动态的修改配置并在不重启服务情况下生效的组件应运而生,今天小编跟大家分享一下xxl-conf这款开源的配置中心。
项目介绍
xxl-conf是一款轻量级、秒级动态推送、多环境配置高性能分布式开源配置管理平台,特性还有很多,有兴趣的童鞋可以看下官方介绍,管理平台的部署和应用端的集成都非常简单,下面跟大家介绍下较实用的几种接入方式,同时会分享下小编对相关实现的理解。
1.管理平台部署
从https://github.com/xuxueli/xxl-conf下载项目,将xxl-conf-admin单独拷贝到自己的创建的项目中(其实直接用就可以了,小编喜欢拷贝过来以便自定义修改),这个模块只需要修改下application.properties中的mysql链接信息以及日志存储路径。
### web
server.port=8080
server.context-path=/xxl-conf-admin
### resources
spring.mvc.static-path-pattern=/static/**
spring.resources.static-locations=classpath:/static/
### freemarker
spring.freemarker.templateLoaderPath=classpath:/templates/
spring.freemarker.suffix=.ftl
spring.freemarker.charset=UTF-8
spring.freemarker.request-context-attribute=request
spring.freemarker.settings.number_format=0.##########
### mybatis
mybatis.mapper-locations=classpath:/mybatis-mapper/*Mapper.xml
### xxl-conf, datasource
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/demo?Unicode=true&characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.type=org.apache.tomcat.jdbc.pool.DataSource
spring.datasource.tomcat.max-wait=10000
spring.datasource.tomcat.max-active=30
spring.datasource.tomcat.test-on-borrow=true
# xxl-conf, confdata
xxl.conf.confdata.filepath=applogs/xxl-conf/confdata
xxl.conf.access.token=
navicat执行目录doc/db下的xxl-conf.sql文件,创建6张表并初始化信息。
启动项目访问地址http://localhost:8080/xxl-conf-admin,并用admin/123456登录
为了演示,小编通过环境管理添加了dev环境。
2.应用端配置
2.1 创建一个新的spring boot module,引入核心jar
<dependency>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-conf-core</artifactId>
<version>1.6.1</version>
</dependency>
2.2 修改application.properties,如下
# web port
server.port=8081
# log config
logging.config=classpath:logback.xml
# xxl-conf
xxl.conf.admin.address=http://localhost:8080/xxl-conf-admin
xxl.conf.env=dev
xxl.conf.access.token=
xxl.conf.mirrorfile=applogs/xxl-conf/xxl-conf-mirror-sample.properties
xxl.conf.admin.address一定要指向管理平台的项目地址
2.3 创建配置类
package com.xxl.conf.demo.config;
import com.xxl.conf.core.spring.XxlConfFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* xxl-conf config
*
* @author xuxueli 2017-04-28
*/
@Configuration
public class XxlConfConfig {
private Logger logger = LoggerFactory.getLogger(XxlConfConfig.class);
@Value("${xxl.conf.admin.address}")
private String adminAddress;
@Value("${xxl.conf.env}")
private String env;
@Value("${xxl.conf.access.token}")
private String accessToken;
@Value("${xxl.conf.mirrorfile}")
private String mirrorfile;
@Bean
public XxlConfFactory xxlConfFactory() {
XxlConfFactory xxlConf = new XxlConfFactory();
xxlConf.setAdminAddress(adminAddress);
xxlConf.setEnv(env);
xxlConf.setAccessToken(accessToken);
xxlConf.setMirrorfile(mirrorfile);
logger.info(">>>>>>>>>>> xxl-conf config init.");
return xxlConf;
}
}
以上3步就完了应用端的搭建。
XxlConfFactory是组件核心类,主流程如下:
初始化信息
初始化管理平台地址信息、配置本地化文件路径信息、缓存本地文件和远程数据到ConcurrentHashMap中
初始化监控线程
创建一个守护线程,死循环轮询本地缓存配置远程是否有更新,存在变更,则更新缓存数据并触发监听器(key的监听器和无key的全局监听器),最后更新本地文件的配置信息
添加监听器
添加无key的全局监听器BeanRefreshXxlConfListener,管理平台修改配置信后被触发,查询修改的属性key对应的IOC容器中的bean的成员变量
3.效果演示
管理平台创建AppName为demo的项目,项目中所有的属性设置,都需要的demo开头。
配置管理中选择刚刚创建的项目"我的例子",并选择dev开发环境,增加配置,如下。
3.1 api方式
XxlConfClient从缓存中获取key对应的值
String paramByApi = XxlConfClient.get("demo.param.by.api", null);
3.2 注解方式
初始化XxlConfFactory时调用postProcessAfterInstantiation方法进行属性注入
@XxlConf("demo.param.by.anno")
public String paramByAnno;
3.3 xml方式
初始化XxlConfFactory时调用postProcessPropertyValues方法进行属性setter方式注入
<bean id="demoConf" class="com.xxl.conf.demo.bean.XmlConfBean">
<property name="paramByXml" value="$XxlConf{demo.param.by.xml}" />
</bean>
与注解方式一样,底层是用反射进行属性设值的。
3.4 属性文件占位符方式
# for test
test.conf=#{T(com.xxl.conf.core.XxlConfClient).get('demo.param.by.properties')}
3.5 配置变更监听
/**
* 配置变更监听示例:可开发Listener逻辑,监听配置变更事件;可据此实现动态刷新JDBC连接池等高级功能;
*/
XxlConfClient.addListener("demo.param.by.anno", new XxlConfListener(){
@Override
public void onChange(String key, String value) throws Exception {
logger.info("配置变更事件通知:{}={}", key, value);
}
});
配置好以上方式后,添加一个测试方法
@RequestMapping("/test")
@ResponseBody
public List<String> index(){
List<String> list = new LinkedList<>();
/**
* 方式1: API方式
*/
String paramByApi = XxlConfClient.get("demo.param.by.api", null);
list.add("1、API方式: default.key01=" + paramByApi);
/**
* 方式2: @XxlConf 注解方式
*/
list.add("2、@XxlConf 注解方式: demo.param.by.anno=" + annotationConfBean.paramByAnno);
/**
* 方式3: XML占位符方式
*/
list.add("3、XML占位符方式: demo.param.by.xml=" + xmlConfBean.paramByXml);
/**
* 方式3: 属性文件占位符方式
*/
list.add("4、读取application.properties demo.param.by.properties =" + annotationConfBean.testConf);
return list;
}
启动项目,访问http://localhost:8081/test
各个方式的值都获取到了,修改管理平台配置如下
查看应用端日志,key为demo.param.by.anno的监听器被触发,守护线程监控的信息也更新了
再次访问http://localhost:8081/test,结果如下
细心的同学会发现属性配置的值并没有改变, 因为前3种方式因修改了本地缓存的配置以及IOC中BeanFactory下bean的信息,拿到了更新后的数据,而属性文件没有被重新加载,还是原来的值。
总结
xxl-conf整个平台的搭建以及集成非常简单易学,但是组件里面的实现的思路是值得我们学习思考的,小编debug源码后,发现其实大多都是熟悉的JDK以及框架类的应用,例如配置信息的秒级更新是利用轮询数据库以及spring mvc中的DeferredResult超时配置进行异步回调来实现。
项目demo地址
https://github.com/pengziliu/GitHub-code-practice
关注后回复代码整洁之道或抽奖
可以抽同名实体书籍,最近都有在送
推荐实战文章
更多精彩...
原创不易,觉得有点用的话,请为本文点个在看,因为这将是我肝轮子的最强动力。公众号对话框回复抽奖,继续送书!!