ApiBoot是一款基于SpringBoot1.x,2.x的接口服务集成基础框架, 内部提供了框架的封装集成、使用扩展、自动化完成配置,让接口开发者能够选着性完成开箱即用, 再也不为搭建接口框架而犯愁,从而极大的提升开发效率。java
顾名思义,DataSource Switch
是用于数据源选择切换的框架,这是一款基于Spring AOP
切面指定注解实现的,经过简单的数据源注解配置就能够完成访问时的自动切换,DataSource Switch
切换过程当中是线程安全的。mysql
使用DataSource Switch
很简单,在pom.xml
配置文件内添加以下依赖:git
<!--ApiBoot DataSource Switch-->
<dependency>
<groupId>org.minbox.framework</groupId>
<artifactId>api-boot-starter-datasource-switch</artifactId>
</dependency>
复制代码
ApiBoot
所提供的依赖都不须要添加版本号,具体查看ApiBoot版本依赖github
目前ApiBoot DataSource Switch
集成了Druid
、HikariCP
两种数据源实现依赖,在使用方面也有必定的差别,由于每个数据源的内置参数不一致。sql
Druid
:参数配置前缀为api.boot.datasource.druid
HikariCP
:参数配置前缀为api.boot.datasource.hikari
具体使用请查看下面功能配置介绍。数据库
参数名 | 参数默认值 | 是否必填 | 参数描述 |
---|---|---|---|
api.boot.datasource.primary |
master | 否 | 主数据源名称 |
api.boot.datasource.druid.{poolName}.url |
无 | 是 | 数据库链接字符串 |
api.boot.datasource.druid.{poolName}.username |
无 | 是 | 用户名 |
api.boot.datasource.druid.{poolName}.password |
无 | 是 | 密码 |
api.boot.datasource.druid.{poolName}.driver-class-name |
com.mysql.cj.jdbc.Driver | 否 | 驱动类型 |
api.boot.datasource.druid.{poolName}.filters |
stat,wall,slf4j | 否 | Druid过滤 |
api.boot.datasource.druid.{poolName}.max-active |
20 | 否 | 最大链接数 |
api.boot.datasource.druid.{poolName}.initial-size |
1 | 否 | 初始化链接数 |
api.boot.datasource.druid.{poolName}.max-wait |
60000 | 否 | 最大等待市场,单位:毫秒 |
api.boot.datasource.druid.{poolName}.validation-query |
select 1 from dual | 否 | 检查sql |
api.boot.datasource.druid.{poolName}.test-while-idle |
true | 否 | 建议配置为true,不影响性能,而且保证安全性。申请链接的时候检测,若是空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测链接是否有效。 |
api.boot.datasource.druid.{poolName}.test-on-borrow |
false | 否 | 申请链接时执行validationQuery检测链接是否有效,作了这个配置会下降性能。 |
api.boot.datasource.druid.{poolName}.test-on-return |
false | 否 | 归还链接时执行validationQuery检测链接是否有效,作了这个配置会下降性能。 |
api.boot.datasource.hikari.{poolName}.url |
无 | 是 | 数据库链接字符串 |
api.boot.datasource.hikari.{poolName}.username |
无 | 是 | 用户名 |
api.boot.datasource.hikari.{poolName}.password |
无 | 是 | 密码 |
api.boot.datasource.hikari.{poolName}.driver-class-name |
com.mysql.cj.jdbc.Driver | 否 | 数据库驱动类全限定名 |
api.boot.datasource.hikari.{poolName}.property |
无 | 否 | HikariCP属性配置 |
HikariCP
数据源是SpringBoot2.x
自带的,配置参数请访问HikariCP。api
ApiBoot DataSource Switch
支持单主数据源的配置,application.yml
配置文件以下所示:安全
api:
boot:
datasource:
# 配置使用hikari数据源
hikari:
# master datasource config
master:
url: jdbc:mysql://localhost:3306/test?characterEncoding=utf8&serverTimezone=Asia/Shanghai
username: root
password: 123456
复制代码
master
为默认的主数据源的poolName
,这里能够进行修改成其余值,不过须要对应修改primary
参数,以下所示:多线程
api:
boot:
datasource:
# 主数据源,默认值为master
primary: main
# 配置使用hikari数据源
hikari:
# main datasource config
main:
url: jdbc:mysql://localhost:3306/test?characterEncoding=utf8&serverTimezone=Asia/Shanghai
username: root
password: 123456
复制代码
在上面配置主数据源的poolName
修改成main
。oracle
若是你的项目内存在单主单从
、一主多从
的配置方式,以下所示:
api:
boot:
datasource:
# 配置使用hikari数据源
hikari:
# master datasource config
master:
url: jdbc:mysql://localhost:3306/test?characterEncoding=utf8&serverTimezone=Asia/Shanghai
username: root
password: 123456
# 默认值为【com.mysql.cj.jdbc.Driver】
#driver-class-name: com.mysql.cj.jdbc.Driver
# slave 1 datasource config
slave_1:
url: jdbc:mysql://localhost:3306/oauth2?characterEncoding=utf8&serverTimezone=Asia/Shanghai
username: root
password: 123456
# slave 2 datasource config
slave_2:
url: jdbc:mysql://localhost:3306/resources?characterEncoding=utf8&serverTimezone=Asia/Shanghai
username: root
password: 123456
复制代码
在上面是一主多从
的配置方式,分别是master
、slave_1
、slave_2
。
ApiBoot DataSource Switch
提供了一个项目内链接多个不一样类型的数据库,如:MySQL
、Oracle
...等,以下所示:
api:
boot:
# 主数据源,默认值为master
primary: mysql
hikari:
mysql:
url: jdbc:mysql://localhost:3306/test?characterEncoding=utf8&serverTimezone=Asia/Shanghai
username: root
password: 123456
oracle:
url: jdbc:oracle:thin:@172.16.10.25:1521:torcl
username: root
password: 123456
driver-class-name: oracle.jdbc.driver.OracleDriver
复制代码
在上面配置中,master
主数据源使用的MySQL
驱动链接MySQL
数据库,而slave
从数据源则是使用的Oracle
驱动链接的Oracle
数据库。
ApiBoot DataSource Switch
内部提供了动态建立数据源的方法,能够经过注入ApiBootDataSourceFactoryBean
来进行添加,以下所示:
@Autowired
private ApiBootDataSourceFactoryBean factoryBean;
public void createNewDataSource() throws Exception {
// 建立Hikari数据源
// 若是建立Druid数据源,使用DataSourceDruidConfig
DataSourceHikariConfig config = new DataSourceHikariConfig();
// 数据库链接:必填
config.setUrl("jdbc:mysql://localhost:3306/resources");
// 用户名:必填
config.setUsername("root");
// 密码:必填
config.setPassword("123456");
// 数据源名称:必填(用于@DataSourceSwitch注解value值使用)
config.setPoolName("dynamic");
// 建立数据源
DataSource dataSource = factoryBean.newDataSource(config);
Connection connection = dataSource.getConnection();
System.out.println(connection.getCatalog());
connection.close();
}
复制代码
ApiBoot DataSource Switch
的数据源自动切换主要归功于Spring
的AOP
,经过切面@DataSourceSwitch
注解,获取注解配置的value
值进行设置当前线程所用的数据源名称,从而经过AbstractRoutingDataSource
进行数据源的路由切换。
咱们沿用上面一主多从的配置进行代码演示,配置文件application.yml
参考上面配置,代码示例以下:
@Service
@DataSourceSwitch("slave")
public class SlaveDataSourceSampleService {
/** * DataSource Instance */
@Autowired
private DataSource dataSource;
/** * 演示输出数据源的catalog * * @throws Exception */
public void print() throws Exception {
// 获取连接
Connection connection = dataSource.getConnection();
// 输出catalog
System.out.println(this.getClass().getSimpleName() + " ->" + connection.getCatalog());
// 关闭连接
connection.close();
}
}
复制代码
@Service
@DataSourceSwitch("master")
public class MasterDataSourceSampleService {
/** * DataSource Instance */
@Autowired
private DataSource dataSource;
/** * Slave Sample Service */
@Autowired
private SlaveDataSourceSampleService slaveDataSourceSampleService;
/** * 演示输出主数据源catalog * 调用从数据源类演示输出catalog * * @throws Exception */
public void print() throws Exception {
Connection connection = dataSource.getConnection();
System.out.println(this.getClass().getSimpleName() + " ->" + connection.getCatalog());
connection.close();
slaveDataSourceSampleService.print();
}
}
复制代码
主数据源
的示例类内,咱们经过@DataSourceSwitch("master")
注解的value
进行定位链接master
数据源数据库。从数据库
的示例类内,咱们也能够经过@DataSourceSwitch("slave")
注解的value
进行定位链接slave
数据源数据库。在上面的测试示例中,咱们使用交叉的方式进行验证数据源路由
是否能够正确的进行切换,能够编写一个单元测试进行验证结果,以下所示:
@Autowired
private MasterDataSourceSampleService masterDataSourceSampleService;
@Test
public void contextLoads() throws Exception {
masterDataSourceSampleService.print();
}
复制代码
运行上面测试方法,结果以下所示:
MasterDataSourceSampleService ->test
2019-04-04 10:20:45.407 INFO 7295 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-2 - Starting...
2019-04-04 10:20:45.411 INFO 7295 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-2 - Start completed.
SlaveDataSourceSampleService ->oauth2
复制代码
单次执行数据源切换没有任何的问题,master
数据源获取catalog
输出后,调用slave
示例类进行输出catalog
。
ApiBoot DataSource Switch
会在项目启动时首先初始化master
节点DataSource
实例,其余实例会在第一次调用时进行初始化。
单次执行单线程操做没有问题,不表明多线程下不会出现问题,在开头说到过ApiBoot DataSource Switch
是线程安全的,因此接下来咱们来验证这一点,咱们须要添加压力测试的依赖,以下所示:
<dependency>
<groupId>org.databene</groupId>
<artifactId>contiperf</artifactId>
<version>2.3.4</version>
<scope>test</scope>
</dependency>
复制代码
接下来把上面的单元测试代码改造下,以下所示:
// 初始化压力性能测试对象
@Rule
public ContiPerfRule i = new ContiPerfRule();
@Autowired
private MasterDataSourceSampleService masterDataSourceSampleService;
/** * 开启500个线程执行10000次 */
@Test
@PerfTest(invocations = 10000, threads = 500)
public void contextLoads() throws Exception {
masterDataSourceSampleService.print();
}
复制代码
测试环境:
硬件:i七、16G、256SSD
系统:OS X
整个过程大约是10秒左右,
ApiBoot DataSource Switch
并无发生出现切换错乱的状况。
ApiBoot DataSource Switch
时须要添加对应数据库的依赖Druid
链接池,不要配置使用druid-starter
的依赖,请使用druid
依赖。poolName
时不要添加特殊字符、中文、中横线等。