解析源码找出 Springboot+ShardingJdbc 对数据库连接池调优属性配置的方式

拈花ヽ惹草 提交于 2020-02-26 10:58:21

问题描述

最近公司搭建springboot项目 由于之前都是使用的spring项目 对于boot的理解还是不深 通过找一些文档搭建好了shardingJdbc分库分表的配置 使用了properties方式 参考官网配置如下

我们项目数据源使用了HikariCP 由于要对于数据连接池进行配置 方便出现问题调优 网上翻遍了配置整合 都是只有springboot初始的Hikari配置 与sharding整合的配置没有涉及到

传统springboot单数据源数据源整合配置

由于使用了分库分表 数据源前缀不同 肯定不能使用之前的配置方式 自己依样画葫芦写了点配置 发现竟然生效了

sharding.jdbc.datasource.ds0.pool-name=Retail_HikariCP0
sharding.jdbc.datasource.ds0.maximum-pool-size = 20

控制台出现了新的cpName!! 这就让我燃起了希望 同时又找到了https://www.cnblogs.com/aut-lory/p/10789573.html 这篇博主的文章 让我下定决心动手debug源码 查看我的配置是否生效 以及到底什么样的前缀配置才会被sharding发现并且注入

问题解决

数据源是spring初始化配置时加载的 很容易联想到spring-shardingjdbc-starter的自动配置 找到starter的factories文件

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
io.shardingsphere.shardingjdbc.spring.boot.SpringBootConfiguration

找到了自动配置类的路径 SpringBootConfiguration


@Configuration
@EnableConfigurationProperties({SpringBootShardingRuleConfigurationProperties.class, SpringBootMasterSlaveRuleConfigurationProperties.class})
public class SpringBootConfiguration implements EnvironmentAware {
    
    @Autowired
    private SpringBootShardingRuleConfigurationProperties shardingProperties;
    
    @Autowired
    private SpringBootMasterSlaveRuleConfigurationProperties masterSlaveProperties;
    
    private final Map<String, DataSource> dataSourceMap = new LinkedHashMap<>();
    
    /**
     * Get data source bean.
     * 
     * @return data source bean
     * @throws SQLException SQL exception
     */
    @Bean
    public DataSource dataSource() throws SQLException {
        return null == masterSlaveProperties.getMasterDataSourceName() 
                ? ShardingDataSourceFactory.createDataSource(dataSourceMap, shardingProperties.getShardingRuleConfiguration(), shardingProperties.getConfigMap(), shardingProperties.getProps())
                : MasterSlaveDataSourceFactory.createDataSource(
                        dataSourceMap, masterSlaveProperties.getMasterSlaveRuleConfiguration(), masterSlaveProperties.getConfigMap(), masterSlaveProperties.getProps());
    }
    
    @Override
    public final void setEnvironment(final Environment environment) {
        setDataSourceMap(environment);
    }
    
    @SuppressWarnings("unchecked")
    private void setDataSourceMap(final Environment environment) {
        String prefix = "sharding.jdbc.datasource.";
        String dataSources = environment.getProperty(prefix + "names");
        for (String each : dataSources.split(",")) {
            try {
                Map<String, Object> dataSourceProps = PropertyUtil.handle(environment, prefix + each, Map.class);
                Preconditions.checkState(!dataSourceProps.isEmpty(), "Wrong datasource properties!");
                DataSource dataSource = DataSourceUtil.getDataSource(dataSourceProps.get("type").toString(), dataSourceProps);
                dataSourceMap.put(each, dataSource);
            } catch (final ReflectiveOperationException ex) {
                throw new ShardingException("Can't find datasource type!", ex);
            }
        }
    }
}


配置类方法很少很容易读懂
当你看到setDataSourceMap方法底下的String prefix = "sharding.jdbc.datasource."; 就应该有灵敏的嗅觉 这里就是解析配置数据源配置文件把他塞到map里 我们就找到了debug的入口
如我们所愿果然debug到了

我们注意方法的参数final Environment environment 我们通过键入environment.getProperty的方法再通过debug界面观察他的属性

可以发现他就是解析了各种配置文件的内容 里面的source字段存放着所有配置文件的key-value 很容易就可以找到我们之前配置的多数据源的配置内容

for (String each : dataSources.split(",")) {
            try {
                Map<String, Object> dataSourceProps = PropertyUtil.handle(environment, prefix + each, Map.class);
                Preconditions.checkState(!dataSourceProps.isEmpty(), "Wrong datasource properties!");
                DataSource dataSource = DataSourceUtil.getDataSource(dataSourceProps.get("type").toString(), dataSourceProps);
                dataSourceMap.put(each, dataSource);
            } catch (final ReflectiveOperationException ex) {
                throw new ShardingException("Can't find datasource type!", ex);
            }
        }

上面的代码则是对我们之前配置的多数据源依次解析配置 注意其中的DataSourceUtil.getDataSource方法

太爽了 直接找到了我们配置的ds0数据的配置 看到我们新加的cpname和max连接数

for (Entry<String, Object> entry : dataSourceProperties.entrySet()) {
            callSetterMethod(result, getSetterMethodName(entry.getKey()), null == entry.getValue() ? null : entry.getValue().toString());
        }

这段for循环则是通过反射判断dataSourceProps里面的内容 按照类型反射使用set方法 存到datasource对象中去。

DataSource result = (DataSource) Class.forName(dataSourceClassName).newInstance();

datasource对象的类型则是第一行代码 反射获取的具体类型,而且里面拥有的属性 在接下来都会一一对应dataSourceProps的key 如果存在再set进数据源对象里进行配置 到这里其实肯定有疑问 dataSourceProps 是怎么解析的呢 让我们回到最初的自动配置的那个循环上

键入之后找到了具体的执行方法

最后返回一个配置文件解析的map

最终结论

如何设置连接池的附加配置 则只需要在sharding.jdbc.datasource.(数据源名) 后直接加上属性内容 如hikari连接池 则类似 sharding.jdbc.datasource.ds0.maximum-pool-size = 20 无需像springboot默认配置 如spring.datasource.hikari.maximum-pool-size=20 加上一个hikari 前缀 (前提是整合的shardingJdbc) 结论十分简单啊 第一次分析源码去解决问题 还是很有成就感的

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!