前言

  最近需要实现一个功能,动态刷新线上数据源环境,下面来使用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动态修改线上数据源的更多相关文章

  1. 【原】fiddler修改线上的内容

    摘要:当我们线上的代码出bug了,咋办呢?有时候本地的代码跟线上的代码还是运行环境还是有区别的.比如有些封装的方法需要运动到手机上可以调试,而浏览器是无法调试的.如果不想每次修改完再放上到测试环境看效 ...

  2. 不停机修改线上 MySQL 主键字段 以及其带来的问题和总结思考

    起因: 线上 user 数据库没有自增字段,数据量已经达到百万级.无论是给离线仓库还是数据分析同步数据,没有主键自增 id 都是杀手级的困难.所以在使用 create_time 痛苦了几次之后准备彻底 ...

  3. log4j2和logback动态修改日志级别工具类

    工作中,在排查线上问题时,有以下场景在不重新部署或重启服务的情况下,需要动态调整线上日志级别 1.线上有些日志打印过多干扰有用的日志,需要动态修改线上日志记录器的打印日志级别,调高一些日志级别,打印出 ...

  4. 【线上问题排查技巧】动态修改LOGGER日志级别

    前言 大多数情况下,我们会在打印日志时定义日志的LOGGER级别,用来控制输出的信息范围. 一方面,过多的输出会影响查看日志的效率,另一方面,过少的日志让问题定位变得困难. 但当线上出现问题时,线上容 ...

  5. 不停机替换线上代码? 你没听错,Arthas它能做到

    写在前边 有没有这样一种感受,自己写的代码在开发.测试环境跑的稳得一笔,可一到线上就抽风,不是缺这个就是少那个反正就是一顿报错,线上调试代码又很麻烦,让人头疼得很.阿里巴巴出了一款名叫Arthas的工 ...

  6. JS动态修改微信浏览器中的title

    JS动态修改微信浏览器中的title我们的原理是设置一个ifame然后我们再加载一下就可以实现了,具体的例子如下所示. 平时使用JS修改title,直接document.title=新标题就好了 这样 ...

  7. chrome浏览器调试线上文件映射本地文件

    chrome浏览器调试线上文件映射本地文件 通过ReRes让chrome拥有路径映射的autoResponse功能. 前端开发过程中,经常会有需要对远程环境调试的需求.比如,修改线上bug,开发环境不 ...

  8. YARN线上动态资源调优

    背景 线上Hadoop集群资源严重不足,可能存在添加磁盘,添加CPU,添加节点的操作,那么在添加这些硬件资源之后,我们的集群是不能立马就利用上这些资源的,需要修改集群Yarn资源配置,然后使其生效. ...

  9. MySQL 分区表 partition线上修改分区字段,后续进一步学习partition (1)

    公司线上在用partition,有一个表的分区字段错了,需要重建,结果发现没有办法像修改主键字段或者修改索引字段那样直接一条sql搞定.而是需要建临时表,有down time,所以去仔细看了文档,研究 ...

随机推荐

  1. [TimLinux] PyQt5 安装部署

    1. 依赖包 Click (7.0) PyQt5 (5.11.2) PyQt5-sip (4.19.12) QScintilla (2.10.7) pip (9.0.1) pyqt5-tools (5 ...

  2. BZOJ 2152 聪聪可可(树形DP)

    聪聪和可可是兄弟俩,他们俩经常为了一些琐事打起来,例如家中只剩下最后一根冰棍而两人都想吃.两个人都想玩儿电脑(可是他们家只有一台电脑)……遇到这种问题,一般情况下石头剪刀布就好了,可是他们已经玩儿腻了 ...

  3. HDU1848 Fibonacci again and again(SG 函数)

    任何一个大学生对菲波那契数列(Fibonacci numbers)应该都不会陌生,它是这样定义的: F(1)=1; F(2)=2; F(n)=F(n-1)+F(n-2)(n>=3); 所以,1, ...

  4. 洛谷 题解 P1600 【天天爱跑步】 (NOIP2016)

    必须得说,这是一道难题(尤其对于我这样普及组205分的蒟蒻) 提交结果(NOIP2016 天天爱跑步): OJ名 编号 题目 状态 分数 总时间 内存 代码 / 答案文件 提交者 提交时间 Libre ...

  5. [FPGA]Verilog 60s秒表计时器(最大可计时间长达9min)

    [FPGA]Verilog 60s秒表计时器 1.引述 这次的实验来自于本人本科课程数电结课时的自选题目.由于这次上传是后知后觉,学校已将小脚丫板子回收,所以在这篇文章中没法贴出代码结果的效果图了,但 ...

  6. 小白进阶—python中os模块用法

    一.os模块概述 python中的os 模块包含普遍的操作系统功能,这个模块不受平台限制,即windows和linux上都适用. 二.常用方法 1.os.name 返回正在使用的平台.如果是windo ...

  7. 【Webpack】320- Webpack4 入门手册(共 18 章)(下)

    介绍 1. 背景 最近和部门老大,一起在研究团队[EFT - 前端新手村]的建设,目的在于:帮助新人快速了解和融入公司团队,帮助零基础新人学习和入门前端开发并且达到公司业务开发水平. 本文也是属于[E ...

  8. Web基础了解版01-html-css

    HTML 网页构成 摘要 说明 结构(HTML) HTML是网页内容的载体.内容就是网页制作者放在页面上想要让用户浏览的信息,可以包含文字.图片.视频等. 表现(CSS) CSS样式是表现.就像网页的 ...

  9. conda docker镜像

    之前的python环境,使用ubuntu安装pip来安装python依赖,但是遇到缺少某些库的版本,比如一个项目需要用到faiss,pip只有最新的1.5.3版本,但是这个版本使用了较新的CPU指令, ...

  10. Idea集成及使用svn插件

    1 idea集成svn 1.1 svn是什么? SVN是subversion的缩写,是一个开放源代码的版本控制系统,通过采用分支管理系统的高效管理,简而言之就是用于多个人共同开发同一个项目,实现共享资 ...