背景:
當前項目使用的
mybatis-plus
多數據源框架,使用方式可參考:https://mp.baomidou.com/guide/dynamic-datasource.html#文檔-documentation
默認多數據源配置,並不支持clickHouse 多節點信息,可通過如下方式擴展:
pom.xml
...
<mybatis.plus.version>3.4.3.4</mybatis.plus.version>
<dynamic.datasource.version>3.4.1</dynamic.datasource.version>
<clickhouse.version>0.3.1-patch</clickhouse.version>
...
<dependency>
<groupId>ru.yandex.clickhouse</groupId>
<artifactId>clickhouse-jdbc</artifactId>
<version>${clickhouse.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis.plus.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>${dynamic.datasource.version}</version>
</dependency>
Java代碼:
增加自定義的動態數據源配置
// 保證執行順序在前面,否則 會被其他加載器給創建,導致自定義的加載器執行不到
@Order(0)
@Configuration
public class DynamicDataSourceConfig extends AbstractDataSourceCreator implements DataSourceCreator {
protected DynamicDataSourceConfig(DynamicDataSourceProperties dynamicDataSourceProperties) {
super(dynamicDataSourceProperties);
}
@Override
public DataSource doCreateDataSource(DataSourceProperty dataSourceProperty) {
// 如果需要其他參數,自行加入,可以在配置文件配置,此處從dataSourceProperty獲取,並填充
Properties properties = new Properties();
// 使用clickHouse
return new BalancedClickhouseDataSource(dataSourceProperty.getUrl(), properties);
}
@Override
public boolean support(DataSourceProperty dataSourceProperty) {
// 適配器模式,判斷是否需要使用當前動態數據源創建
Class<? extends DataSource> type = dataSourceProperty.getType();
if (Objects.isNull(type)) {
return Boolean.FALSE;
}
return StringUtils.equals(type.getName(), BalancedClickhouseDataSource.class.getName());
}
}
使用方式
// 標注此 mapper 查詢使用 clickHouse 數據源,和 配置文件中名稱對應
@DS("clickHouse")
public interface TestMapper extends BaseMapper<TestEntity> {
}
application.yaml
spring:
datasource:
dynamic:
primary: master #指定默認數據源
strict: true
datasource:
master:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://xxxx:3306/xxx?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&zeroDateTimeBehavior=convertToNull
username: xx
password: xx
hikari:
minimum-idle: 5
idle-timeout: 600000
maximum-pool-size: 20
max-lifetime: 1800000
connection-timeout: 6000
connection-test-query: SELECT 1
clickHouse:
# 此處type 主要用作 java代碼中適配器的判斷
type: ru.yandex.clickhouse.BalancedClickhouseDataSource
driver-class-name: ru.yandex.clickhouse.ClickHouseDriver
# jdbc:clickhouse://ip:port,ip:port/xxx 配置格式
url: jdbc:clickhouse://xxxx:8123,xxxx:8123/xxx
原理解析
BalancedClickhouseDataSource.class
此數據源為
clickHouse
jdbc提供的集群DataSource
所以我們要做的就是使用此數據源來創建
DataSource
/**
* create Datasource for clickhouse JDBC connections
*
* @param url address for connection to the database
* must have the next format {@code jdbc:clickhouse://<first-host>:<port>,<second-host>:<port>/<database>?param1=value1¶m2=value2 }
* for example, {@code jdbc:clickhouse://localhost:8123,localhost:8123/database?compress=1&decompress=2 }
* @throws IllegalArgumentException if param have not correct format, or error happens when checking host availability
*/
public BalancedClickhouseDataSource(final String url) {
this(splitUrl(url), getFromUrl(url));
}
com.baomidou.dynamic.datasource.creator.DefaultDataSourceCreator
源碼中,通過此類來初始化配置文件中的 數據源
@Slf4j
@Setter
public class DefaultDataSourceCreator {
// 默認的實現類中,BasicDataSourceCreator 的 support方法始終為true,所以自定義的動態數據源配置,必須在 BasicDataSourceCreator 之前執行,需要設置 @Order
private List<DataSourceCreator> creators;
public DataSource createDataSource(DataSourceProperty dataSourceProperty) {
DataSourceCreator dataSourceCreator = null;
for (DataSourceCreator creator : this.creators) {
// 適配器判斷,是否使用此數據源
if (creator.support(dataSourceProperty)) {
dataSourceCreator = creator;
break;
}
}
if (dataSourceCreator == null) {
throw new IllegalStateException("creator must not be null,please check the DataSourceCreator");
}
// 創建數據源
return dataSourceCreator.createDataSource(dataSourceProperty);
}
}