ApiBoot DataSource Switch 使用文檔

ApiBoot是一款基于SpringBoot1.x,2.x的接口服務(wù)集成基礎(chǔ)框架, 內(nèi)部提供了框架的封裝集成、使用擴(kuò)展、自動(dòng)化完成配置,讓接口開發(fā)者可以選著性完成開箱即用, 不再為搭建接口框架而犯愁,從而極大的提高開發(fā)效率。

ApiBoot DataSource Switch

顧名思義,DataSource Switch是用于數(shù)據(jù)源選擇切換的框架,這是一款基于Spring AOP切面指定注解實(shí)現(xiàn)的,通過簡單的數(shù)據(jù)源注解配置就可以完成訪問時(shí)的自動(dòng)切換,DataSource Switch切換過程中是線程安全的。

添加依賴

使用DataSource Switch很簡單,在pom.xml配置文件內(nèi)添加如下依賴:

<!--ApiBoot DataSource Switch-->
<dependency>
  <groupId>org.minbox.framework</groupId>
  <artifactId>api-boot-starter-datasource-switch</artifactId>
</dependency>

ApiBoot所提供的依賴都不需要添加版本號(hào),具體查看ApiBoot版本依賴

集成數(shù)據(jù)源實(shí)現(xiàn)

目前ApiBoot DataSource Switch集成了DruidHikariCP兩種數(shù)據(jù)源實(shí)現(xiàn)依賴,在使用方面也有一定的差異,因?yàn)槊恳粋€(gè)數(shù)據(jù)源的內(nèi)置參數(shù)不一致。

  • Druid:參數(shù)配置前綴為api.boot.datasource.druid
  • HikariCP:參數(shù)配置前綴為api.boot.datasource.hikari

具體使用請(qǐng)查看下面功能配置介紹。

配置參數(shù)

參數(shù)名 參數(shù)默認(rèn)值 是否必填 參數(shù)描述
api.boot.datasource.primary master 主數(shù)據(jù)源名稱
api.boot.datasource.druid.{poolName}.url 數(shù)據(jù)庫連接字符串
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 驅(qū)動(dòng)類型
api.boot.datasource.druid.{poolName}.filters stat,wall,slf4j Druid過濾
api.boot.datasource.druid.{poolName}.max-active 20 最大連接數(shù)
api.boot.datasource.druid.{poolName}.initial-size 1 初始化連接數(shù)
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,不影響性能,并且保證安全性。申請(qǐng)連接的時(shí)候檢測,如果空閑時(shí)間大于timeBetweenEvictionRunsMillis,執(zhí)行validationQuery檢測連接是否有效。
api.boot.datasource.druid.{poolName}.test-on-borrow false 申請(qǐng)連接時(shí)執(zhí)行validationQuery檢測連接是否有效,做了這個(gè)配置會(huì)降低性能。
api.boot.datasource.druid.{poolName}.test-on-return false 歸還連接時(shí)執(zhí)行validationQuery檢測連接是否有效,做了這個(gè)配置會(huì)降低性能。
api.boot.datasource.hikari.{poolName}.url 數(shù)據(jù)庫連接字符串
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 數(shù)據(jù)庫驅(qū)動(dòng)類全限定名
api.boot.datasource.hikari.{poolName}.property HikariCP屬性配置

HikariCP數(shù)據(jù)源是SpringBoot2.x自帶的,配置參數(shù)請(qǐng)?jiān)L問HikariCP

單主配置

ApiBoot DataSource Switch支持單主數(shù)據(jù)源的配置,application.yml配置文件如下所示:

api:
  boot:
    datasource:
      # 配置使用hikari數(shù)據(jù)源
      hikari:
        # master datasource config
        master:
          url: jdbc:mysql://localhost:3306/test?characterEncoding=utf8&serverTimezone=Asia/Shanghai
          username: root
          password: 123456

修改主數(shù)據(jù)源名稱

master為默認(rèn)的主數(shù)據(jù)源的poolName,這里可以進(jìn)行修改為其他值,不過需要對(duì)應(yīng)修改primary參數(shù),如下所示:

api:
  boot:
    datasource:
      # 主數(shù)據(jù)源,默認(rèn)值為master
      primary: main
      # 配置使用hikari數(shù)據(jù)源
      hikari:
        # main datasource config
        main:
          url: jdbc:mysql://localhost:3306/test?characterEncoding=utf8&serverTimezone=Asia/Shanghai
          username: root
          password: 123456

在上面配置主數(shù)據(jù)源的poolName修改為main。

主從配置

如果你的項(xiàng)目內(nèi)存在單主單從一主多從的配置方式,如下所示:

api:
  boot:
    datasource:
      # 配置使用hikari數(shù)據(jù)源
      hikari:
        # master datasource config
        master:
          url: jdbc:mysql://localhost:3306/test?characterEncoding=utf8&serverTimezone=Asia/Shanghai
          username: root
          password: 123456
          # 默認(rèn)值為【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

在上面是一主多從的配置方式,分別是masterslave_1、slave_2

多類型數(shù)據(jù)庫配置

ApiBoot DataSource Switch提供了一個(gè)項(xiàng)目內(nèi)連接多個(gè)不同類型的數(shù)據(jù)庫,如:MySQL、Oracle...等,如下所示:

api:
  boot:
      # 主數(shù)據(jù)源,默認(rèn)值為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主數(shù)據(jù)源使用的MySQL驅(qū)動(dòng)連接MySQL數(shù)據(jù)庫,而slave從數(shù)據(jù)源則是使用的Oracle驅(qū)動(dòng)連接的Oracle數(shù)據(jù)庫。

動(dòng)態(tài)創(chuàng)建數(shù)據(jù)源

ApiBoot DataSource Switch內(nèi)部提供了動(dòng)態(tài)創(chuàng)建數(shù)據(jù)源的方法,可以通過注入ApiBootDataSourceFactoryBean來進(jìn)行添加,如下所示:

@Autowired
private ApiBootDataSourceFactoryBean factoryBean;

public void createNewDataSource() throws Exception {
  // 創(chuàng)建Hikari數(shù)據(jù)源
  // 如果創(chuàng)建Druid數(shù)據(jù)源,使用DataSourceDruidConfig
  DataSourceHikariConfig config = new DataSourceHikariConfig();
  // 數(shù)據(jù)庫連接:必填
  config.setUrl("jdbc:mysql://localhost:3306/resources");
  // 用戶名:必填
  config.setUsername("root");
  // 密碼:必填
  config.setPassword("123456");
  // 數(shù)據(jù)源名稱:必填(用于@DataSourceSwitch注解value值使用)
  config.setPoolName("dynamic");

  // 創(chuàng)建數(shù)據(jù)源
  DataSource dataSource = factoryBean.newDataSource(config);
  Connection connection = dataSource.getConnection();
  System.out.println(connection.getCatalog());
  connection.close();
}

自動(dòng)切換

ApiBoot DataSource Switch的數(shù)據(jù)源自動(dòng)切換主要?dú)w功于SpringAOP,通過切面@DataSourceSwitch注解,獲取注解配置的value值進(jìn)行設(shè)置當(dāng)前線程所用的數(shù)據(jù)源名稱,從而通過AbstractRoutingDataSource進(jìn)行數(shù)據(jù)源的路由切換。

我們沿用上面一主多從的配置進(jìn)行代碼演示,配置文件application.yml參考上面配置,代碼示例如下:

從數(shù)據(jù)源示例類

@Service
@DataSourceSwitch("slave")
public class SlaveDataSourceSampleService {
    /**
     * DataSource Instance
     */
    @Autowired
    private DataSource dataSource;

    /**
     * 演示輸出數(shù)據(jù)源的catalog
     *
     * @throws Exception
     */
    public void print() throws Exception {
        // 獲取鏈接
        Connection connection = dataSource.getConnection();
        // 輸出catalog
        System.out.println(this.getClass().getSimpleName() + " ->" + connection.getCatalog());
        // 關(guān)閉鏈接
        connection.close();
    }
}

主數(shù)據(jù)源示例類

@Service
@DataSourceSwitch("master")
public class MasterDataSourceSampleService {
    /**
     * DataSource Instance
     */
    @Autowired
    private DataSource dataSource;
    /**
     * Slave Sample Service
     */
    @Autowired
    private SlaveDataSourceSampleService slaveDataSourceSampleService;

    /**
     * 演示輸出主數(shù)據(jù)源catalog
     * 調(diào)用從數(shù)據(jù)源類演示輸出catalog
     * 
     * @throws Exception
     */
    public void print() throws Exception {
        Connection connection = dataSource.getConnection();
        System.out.println(this.getClass().getSimpleName() + " ->" + connection.getCatalog());
        connection.close();
        slaveDataSourceSampleService.print();
    }
}
  • 主數(shù)據(jù)源的示例類內(nèi),我們通過@DataSourceSwitch("master")注解的value進(jìn)行定位連接master數(shù)據(jù)源數(shù)據(jù)庫。
  • 同樣在從數(shù)據(jù)庫的示例類內(nèi),我們也可以通過@DataSourceSwitch("slave")注解的value進(jìn)行定位連接slave數(shù)據(jù)源數(shù)據(jù)庫。

單元測試示例

在上面的測試示例中,我們使用交叉的方式進(jìn)行驗(yàn)證數(shù)據(jù)源路由是否可以正確的進(jìn)行切換,可以編寫一個(gè)單元測試進(jìn)行驗(yàn)證結(jié)果,如下所示:

@Autowired
private MasterDataSourceSampleService masterDataSourceSampleService;
@Test
public void contextLoads() throws Exception {
    masterDataSourceSampleService.print();
}

運(yùn)行上面測試方法,結(jié)果如下所示:

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

單次執(zhí)行數(shù)據(jù)源切換沒有任何的問題,master數(shù)據(jù)源獲取catalog輸出后,調(diào)用slave示例類進(jìn)行輸出catalog。

ApiBoot DataSource Switch會(huì)在項(xiàng)目啟動(dòng)時(shí)首先初始化master節(jié)點(diǎn)DataSource實(shí)例,其他實(shí)例會(huì)在第一次調(diào)用時(shí)進(jìn)行初始化。

壓力性能測試

單次執(zhí)行單線程操作沒有問題,不代表多線程下不會(huì)出現(xiàn)問題,在開頭說到過ApiBoot DataSource Switch是線程安全的,所以接下來我們來驗(yàn)證這一點(diǎn),我們需要添加壓力測試的依賴,如下所示:

<dependency>
  <groupId>org.databene</groupId>
  <artifactId>contiperf</artifactId>
  <version>2.3.4</version>
  <scope>test</scope>
</dependency>

接下來把上面的單元測試代碼改造下,如下所示:

// 初始化壓力性能測試對(duì)象
@Rule
public ContiPerfRule i = new ContiPerfRule();

@Autowired
private MasterDataSourceSampleService masterDataSourceSampleService;
/**
* 開啟500個(gè)線程執(zhí)行10000次
*/
@Test
@PerfTest(invocations = 10000, threads = 500)
public void contextLoads() throws Exception {
  masterDataSourceSampleService.print();
}

測試環(huán)境:

硬件:i7、16G、256SSD

系統(tǒng):OS X

整個(gè)過程大約是10秒左右,ApiBoot DataSource Switch并沒有發(fā)生出現(xiàn)切換錯(cuò)亂的情況。

注意事項(xiàng)

  1. 在使用ApiBoot DataSource Switch時(shí)需要添加對(duì)應(yīng)數(shù)據(jù)庫的依賴
  2. 如果使用Druid連接池,不要配置使用druid-starter的依賴,請(qǐng)使用druid依賴。
  3. 配置poolName時(shí)不要添加特殊字符、中文、中橫線等。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 這篇文章是基于我開發(fā)讀寫分離中間件和數(shù)據(jù)庫智能運(yùn)維平臺(tái)時(shí)的經(jīng)驗(yàn)總結(jié)而成。網(wǎng)上對(duì)數(shù)據(jù)庫連接系統(tǒng)分析的文章非常少,甚至...
    彥幀閱讀 5,206評(píng)論 0 4
  • Druid.io(以下簡稱Druid)是面向海量數(shù)據(jù)的、用于實(shí)時(shí)查詢與分析的OLAP存儲(chǔ)系統(tǒng)。Druid的四大關(guān)鍵...
    大詩兄_zl閱讀 6,560評(píng)論 0 9
  • 1. 簡介 1.1 什么是 MyBatis ? MyBatis 是支持定制化 SQL、存儲(chǔ)過程以及高級(jí)映射的優(yōu)秀的...
    笨鳥慢飛閱讀 6,248評(píng)論 0 4
  • Spark SQL, DataFrames and Datasets Guide Overview SQL Dat...
    草里有只羊閱讀 18,557評(píng)論 0 85
  • xeniam閱讀 404評(píng)論 0 1

友情鏈接更多精彩內(nèi)容