使用Apollo动态修改线上数据源
前言
最近需要实现一个功能,动态刷新线上数据源环境,下面来使用Apollo配置中心和Spring提供的AbstractRoutingDataSource来实现。
具体实现
Apollo是携程开源的统一配置中心,和springboot无缝衔接并且不需要安装其他软件就可以直接使用,可以实时推送最新的配置文件。Spring提供的AbstractRoutingDataSource用于动态管理数据源,可以动态更新数据源,一般数据库的读写分离也是用这个抽象类实现的。
对Apollo不熟悉的可以先了解一下,GitHub:https://github.com/ctripcorp/apollo
关于AbstractRoutingDataSource,介绍一下我们用到的方法
public abstract class AbstractRoutingDataSource extends AbstractDataSource implements InitializingBean { //传入的数据源
private Map<Object, Object> targetDataSources; //拿着子类实现的determineCurrentLookupKey()方法的返回值当做key在这个Map中寻找数据源
private Map<Object, DataSource> resolvedDataSources; //放入多个数据源
public void setTargetDataSources(Map<Object, Object> targetDataSources) {
this.targetDataSources = targetDataSources;
} //属性设置完成后执行
public void afterPropertiesSet() {
if (this.targetDataSources == null) {
throw new IllegalArgumentException("Property 'targetDataSources' is required");
} else {
this.resolvedDataSources = new HashMap(this.targetDataSources.size());
Iterator var1 = this.targetDataSources.entrySet().iterator(); while(var1.hasNext()) {
Entry<Object, Object> entry = (Entry)var1.next();
Object lookupKey = this.resolveSpecifiedLookupKey(entry.getKey());
DataSource dataSource = this.resolveSpecifiedDataSource(entry.getValue());
this.resolvedDataSources.put(lookupKey, dataSource);
} if (this.defaultTargetDataSource != null) {
this.resolvedDefaultDataSource = this.resolveSpecifiedDataSource(this.defaultTargetDataSource);
} }
} protected Object resolveSpecifiedLookupKey(Object lookupKey) {
return lookupKey;
} //子类要实现的抽象方法,数据源的获取策略
protected abstract Object determineCurrentLookupKey();
}
下面来实现通过Apollo动态修改数据源:
@Configuration
public class DataSourceConfiguration { private final static String DATASOURCE_TAG = "db"; @Autowired
ApplicationContext context; @ApolloConfig
Config config; @Bean("dataSource")
public DynamicDataSource dynamicDataSource() {
//使用springboot默认的连接池
DynamicDataSource source = new DynamicDataSource();
//只有一个数据源,传入的Map的key为db,value为使用的数据源
source.setTargetDataSources(Collections.singletonMap(DATASOURCE_TAG, dataSource()));
return source;
} //Apollo监听配置是否修改
@ApolloConfigChangeListener
public void onChange(ConfigChangeEvent changeEvent) {
SetchangedKeys = changeEvent.changedKeys();
if (changedKeys.contains("spring.datasource.url")) {
DynamicDataSource source = context.getBean(DynamicDataSource.class);
//当检测到数据库地址改变时,重新设置数据源
source.setTargetDataSources(Collections.singletonMap(DATASOURCE_TAG, dataSource()));
//调用该方法刷新resolvedDataSources,下次获取数据源时将获取到新设置的数据源
source.afterPropertiesSet();
}
}
public DataSource dataSource() {
HikariDataSource dataSource = new HikariDataSource();
dataSource.setJdbcUrl(config.getProperty("spring.datasource.url", ""));
dataSource.setUsername(config.getProperty("spring.datasource.username", ""));
dataSource.setPassword(config.getProperty("spring.datasource.password", ""));
return dataSource;
} //简单实现AbstractRoutingDataSource,因为只是有一个数据源,所以任何时候选择的数据源都一样
class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() { return DATASOURCE_TAG; }
}
}
determineCurrentLookupKey
使用Apollo动态修改线上数据源的更多相关文章
- 【原】fiddler修改线上的内容
摘要:当我们线上的代码出bug了,咋办呢?有时候本地的代码跟线上的代码还是运行环境还是有区别的.比如有些封装的方法需要运动到手机上可以调试,而浏览器是无法调试的.如果不想每次修改完再放上到测试环境看效 ...
- 不停机修改线上 MySQL 主键字段 以及其带来的问题和总结思考
起因: 线上 user 数据库没有自增字段,数据量已经达到百万级.无论是给离线仓库还是数据分析同步数据,没有主键自增 id 都是杀手级的困难.所以在使用 create_time 痛苦了几次之后准备彻底 ...
- log4j2和logback动态修改日志级别工具类
工作中,在排查线上问题时,有以下场景在不重新部署或重启服务的情况下,需要动态调整线上日志级别 1.线上有些日志打印过多干扰有用的日志,需要动态修改线上日志记录器的打印日志级别,调高一些日志级别,打印出 ...
- 【线上问题排查技巧】动态修改LOGGER日志级别
前言 大多数情况下,我们会在打印日志时定义日志的LOGGER级别,用来控制输出的信息范围. 一方面,过多的输出会影响查看日志的效率,另一方面,过少的日志让问题定位变得困难. 但当线上出现问题时,线上容 ...
- 不停机替换线上代码? 你没听错,Arthas它能做到
写在前边 有没有这样一种感受,自己写的代码在开发.测试环境跑的稳得一笔,可一到线上就抽风,不是缺这个就是少那个反正就是一顿报错,线上调试代码又很麻烦,让人头疼得很.阿里巴巴出了一款名叫Arthas的工 ...
- JS动态修改微信浏览器中的title
JS动态修改微信浏览器中的title我们的原理是设置一个ifame然后我们再加载一下就可以实现了,具体的例子如下所示. 平时使用JS修改title,直接document.title=新标题就好了 这样 ...
- chrome浏览器调试线上文件映射本地文件
chrome浏览器调试线上文件映射本地文件 通过ReRes让chrome拥有路径映射的autoResponse功能. 前端开发过程中,经常会有需要对远程环境调试的需求.比如,修改线上bug,开发环境不 ...
- YARN线上动态资源调优
背景 线上Hadoop集群资源严重不足,可能存在添加磁盘,添加CPU,添加节点的操作,那么在添加这些硬件资源之后,我们的集群是不能立马就利用上这些资源的,需要修改集群Yarn资源配置,然后使其生效. ...
- MySQL 分区表 partition线上修改分区字段,后续进一步学习partition (1)
公司线上在用partition,有一个表的分区字段错了,需要重建,结果发现没有办法像修改主键字段或者修改索引字段那样直接一条sql搞定.而是需要建临时表,有down time,所以去仔细看了文档,研究 ...
随机推荐
- 线性规划VB求解
线性规划VB求解 Rem 定义动态数组 Dim a() As Single, c() As Single, b() As Single, cb() As Single Dim aa() As Sing ...
- Cesium专栏-大量gltf三维模型加载
Cesium 是一款面向三维地球和地图的,世界级的JavaScript开源产品.它提供了基于JavaScript语言的开发包,方便用户快速搭建一款零插件的虚拟地球Web应用,并在性能,精度,渲染质量以 ...
- ARTS-S centos查看端口被哪个进程占用
netstat -tunlp | grep 80 或者 lsof -i:80
- vs里 .sln和.suo 文件 Visual Studio里*.sln和*.suo文件的作用
Visual Studio里*.sln和*.suo文件的作用 VS项目采用两种文件类型(.sln 和 .suo)来存储特定于解决方案的设置.这些文件总称为解决方案文件,为解决方案资源 ...
- .NetCore部署到CentOS
“天下熙熙,皆为利来:天下攘攘,皆为利往.”,越来越多的人涌入IT这个行业,使得技术发展日新月异之外,也会无情淘汰跟不上潮流的人,所以作为IT从业人员,一定要时刻关注前沿技术,免得有朝一日被拍在沙滩上 ...
- Callable接口实现线程
public class CallableDemo { public static void main(String[] args) throws Exception, ExecutionExcept ...
- Java做成Zip文件,Java实现压缩文件
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import ...
- docker进阶之路-基础篇 | 一:环境搭建
转载请注明作者及出处: 作者:银河架构师 原文链接:https://www.cnblogs.com/luas/p/12061747.html 一.准备工作 查看内核 Docker 要求 CentOS ...
- Springboot静态页面放在static路径下还是访问不到
一种最常见的问题,静态资源放在默认的目录,如:resources/static或resources/templates 访问静态资源的时候,路径不应带上默认目录,因为springboot默认从这些目录 ...
- 【ES6】数组的扩展——扩展运算符
1.扩展运算符[三个点(...)将一个数组转为用逗号分隔的参数序列] 作用:用于函数调用 function add(x, y) { return x + y; } const numbers = [2 ...