前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Apollo应用之动态调整线上数据源(DataSource)

Apollo应用之动态调整线上数据源(DataSource)

原创
作者头像
kl博主
发布2018-04-13 16:28:45
2.8K1
发布2018-04-13 16:28:45
举报
文章被收录于专栏:kl的专栏kl的专栏
Apollo应用之动态调整线上数据源(DataSource)
Apollo应用之动态调整线上数据源(DataSource)

前言碎语

博主之前写过使用apollo的配置动态推送能力来动态修改线上环境的日志输出级别,具体可见《spring boot动态调整线上日志级别》,今天来实现一个类似的应用场景,动态变更线上数据源。主要应用场景如:测试时不重启服务切换数据源,准生产无缝切换生产环境,应用端读写分离策略动态化等等,更多的使用场景欢迎在留言区补充。

实现思路

通过对主流数据源(c3p0,dbcp2,tomcat jdbc,Hikari)实现的代理,来动态管理应用到数据库的连接,以及实现应用端的读写分离数据链接策略。如上,spring已经有个抽象类AbstractRoutingDataSource很好的实现了。通过AbstractRoutingDataSource对DataSource的管理,使用apollo配置动态推送能力,动态修改AbstractRoutingDataSource中resolvedDataSources数据源实例,可以很好的实现动态变更线上数据源。

关于AbstractRoutingDataSource

AbstractRoutingDataSource使用Map resolvedDataSources保存了所有可用的数据源实例,预留了一个方法determineCurrentLookupKey给子类去决定使用哪个数据源。这个方法的返回值就是resolvedDataSources中对应的key值,通过这个可以轻松实现应用层面的数据读写分离。当应用程序请求连接时,它拿着子类实现返回的结果去resolvedDataSources中寻找真实的数据源拿数据连接。

具体实现

代码语言:javascript
复制
/**
 * @author : kl * @authorboke : kailing.pub
 * @create : 2018-03-31 下午5:54
 * @description:
 **/
@Configuration
@EnableConfigurationProperties(DataSourceProperties.class)
public class DataSourceConfiguration {

    Logger logger = LoggerFactory.getLogger(getClass());

    private final static String DATASOURCE_TAG = "db";

    @Autowired
    ApplicationContext context;

    @ApolloConfig
    Config config;

    @Bean("dataSource")
    public DynamicDataSource dynamicDataSource() {
        DynamicDataSource source = new DynamicDataSource();
        source.setTargetDataSources(Collections.singletonMap(DATASOURCE_TAG, dataSource()));
        return source;
    }
    @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()));
            source.afterPropertiesSet();
            logger.info("动态切换数据源为:{}", config.getProperty("spring.datasource.url", ""));
        }
    }
    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;
    }
    class DynamicDataSource extends AbstractRoutingDataSource {
        @Override
        protected Object determineCurrentLookupKey() { return DATASOURCE_TAG; }
    }
}

实例环境说明

1.本文实现基于spring boot2.0的环境,spring boot2.0中默认数据库连接池用的Hikari,这个连接池性能不俗,按官方说法,他们在程序基础数据结构,字节码,编译器级别做了大量优化,来保证Hikari的优异性能。从spirng boot 切换tomcat jdbc默认实现这波操作来看,Hikari这款连接池的性能应该不赖。

2.spring boot默认开启了DataSource的自动装配,可以通过@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)这种方式排除自动装配

ps:

我的博客即将搬运同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=2rgybmkkwtusk

文末结语

通过apollo配置动态推送能力,结合AbstractRoutingDataSource,可以轻松实现线上数据源的动态切换。当然,不仅仅是数据库的数据连接可以动态切换,按照上面的设计实现思路,通过apollo的动态配置能力,可以轻松实现很多的线上动态切换。关于线上数据源切换的应用场景,以及apollo的更多应用场景,欢迎大家在下面留言区留言补充。文中提到的Apollo是携程开源的配置中心项目,顺道推广下。项目地址如下

Apollo项目地址:https://github.com/ctripcorp/apollo

Apollo配置中心技术支持QQ群:375526581,加群可以和博主畅聊技术

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
微服务引擎 TSE
微服务引擎(Tencent Cloud Service Engine)提供开箱即用的云上全场景微服务解决方案。支持开源增强的云原生注册配置中心(Zookeeper、Nacos 和 Apollo),北极星网格(腾讯自研并开源的 PolarisMesh)、云原生 API 网关(Kong)以及微服务应用托管的弹性微服务平台。微服务引擎完全兼容开源版本的使用方式,在功能、可用性和可运维性等多个方面进行增强。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档