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