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
時不要添加特殊字符、中文、中橫線等。