前言

  最近需要实现一个功能,动态刷新线上数据源环境,下面来使用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. DOM中的获得元素的方式

    获取元素的方式:分为俩种: 1.直接获取:直接获取分为三种: a,获取单个元素: function demo1(){ var uid=document.getElementById("use ...

  2. Pyhton表白代码——浪漫圣诞节

    圣诞节即将到了,所以这回通过turtle模块来编写一个表白的小程序 开发时间:2019-12-15 开发工具:Sublime 开发模块:turtle 这里用到了turtle库的相关知识,如果不熟悉可以 ...

  3. Docker学习-环境搭建

    ChuanGoing 2019-12-15 本篇是DevOps Docker介绍第一篇,首先说下为何另开一篇来讲解本系列. 原因有二: 1.重新复习下个人对于DevOps/Docker的学习之路 2. ...

  4. layim手机版嵌入app

    感觉记忆力不行了,才做了就有点忘了.先简单做下记录... 遇到的问题 需要类似微信的语音发送功能 前端发送给后端,在mogodb中用二进制存储.后端取到数据发送给我的也是blob.前端拿到数据就变了. ...

  5. docker入门-镜像管理命令篇

    一.下载.上传镜像   1:下载安装centos镜像 语法:docker [参数][镜像名称] [root@host1 ~]# docker pull centos Using default tag ...

  6. windows系统的python开发环境的搭建

    step1:  访问python官方网站下载python安装包 https://www.python.org/downloads/windows/ 下载自己想要的版本 勾上Add Python XX ...

  7. 一线大厂Java面试必问的2大类Tomcat调优

    一.前言 最近整理了 Tomcat 调优这块,基本上面试必问,于是就花了点时间去搜集一下 Tomcat 调优都调了些什么,先记录一下调优手段,更多详细的原理和实现以后用到时候再来补充记录,下面就来介绍 ...

  8. Ubuntu 18.04 根目录只有 4G 大小

    其实准确点儿的描述应该是:Ubuntu Server 18.04 ,设置 LVM,安装完成后根目录的容量为什么只有 4G?只有 Server 版有问题,Desktop 版没有问题,Ubuntu 16. ...

  9. java面试题干货1-50

    1.面向对象的特征有哪些方面? 答:面向对象的特征主要有以下几个方面: - 抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面.抽象只关注对象有哪些属性和行为,并不关注 ...

  10. Java开发图片浏览器--记录

    效果 设计思路 需求分析 图片浏览,上/下一张,放大缩小等基本功能.可以继续拓展的功能:缩略图.旋转,画笔修改等.此外,缩放实现较为简单,所以会出现失真.设计此类软件功能可参考ACDSee或irfan ...