1. 概述
本教程將教您如何使用 FlexyPool 與 Spring Boot 和 H2,並使用 HikariCP。它是一個建立在主要連接池之上,功能強大的連接池管理器。
2. FlexyPool 簡介
連接池是現代 Web 應用程序中的一項重要組成部分。它確保數據庫連接在多個客户端之間共享,從而實現更快速、更高效的數據庫訪問。
然而,管理連接池可能是一個複雜且具有挑戰性的任務,尤其是在客户端數量和應用程序複雜性增加時。 FlexyPool 正是為此而設計的。
FlexyPool 是一款強大的連接池管理工具。它簡化了數據庫連接的管理和性能優化。 簡單來説,FlexyPool 作為代理,與 Hikari、C3P0、DBCP2、Tomcat 和 Vibur 這樣的主要連接池進行交互。 為了實現其目標,該庫提供指標和按需調整池大小的故障轉移策略:
2.1. FlexyPool 屬性
FlexyPool 提供兩個重要的屬性:
- connectionAcquireTimeThresholdMillis:指定連接獲取請求的時間閾值。超過該閾值,將發佈 ConnectionAcquireTimeThresholdExceededEvent 事件。
- connectionLeaseTimeThresholdMillis:連接可以被租借出去的最大時間,在此時間之後,連接將被返回到池中。Flexypool 在池中超過該閾值時,將發佈 ConnectionLeaseTimeThresholdExceededEvent 事件。
2.2. FlexyPool 策略
FlexyPool 提供兩種策略來應對連接池中連接獲取失敗的情況。
第一種策略是 <em>IncrementPoolOnTimeoutConnectionAcquiringStrategy</em>。 通過這種策略,當連接獲取過程中出現超時時,FlexyPool 會增加目標連接池的最大大小。 該策略提供兩個選項:<em>maxOverflowPoolSize</em> 和 <em>timeoutMillis</em>。
<em>maxOverflowPoolSize</em> 設置目標連接池可以擴展的最大限制。
<em>timeoutMillis</em> 設置嘗試增加池大小的持續時間。 默認情況下,該值與連接池超時值相同。
<em>RetryConnectionAcquiringStrategy</em> 指示 FlexyPool 在放棄之前,嘗試從池中獲取連接 <em>retryAttempts</em> 次。 <em>retryAttempts</em> 表示嘗試的重試次數。
我們將所有這些策略配置在 <em>FlexyPoolDataSource</em> 配置中。
3. 安裝
首先,讓我們安裝 HikariCP 連接池:
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>5.1.0</version>
</dependency>接下來,我們將添加 FlexyPool 依賴項,HikariCP 適配器,以及 Micrometer 適配器:
<dependency>
<groupId>com.vladmihalcea.flexy-pool</groupId>
<artifactId>flexy-hikaricp</artifactId>
<version>2.2.3</version>
<exclusions>
<exclusion>
<groupId>com.vladmihalcea.flexy-pool</groupId>
<artifactId>flexy-dropwizard-metrics</artifactId>
</exclusion>
</exclusions>
</dependency><dependency>
<groupId>com.vladmihalcea.flexy-pool</groupId>
<artifactId>flexy-micrometer-metrics</artifactId>
<version>2.2.3</version>
</dependency>由於我們使用 Micrometer 作為指標實現,因此已排除默認的 Dropwizard-Metrics。此外,FlexyPool 提供了 安裝指南,用於其他支持的連接池框架。如果使用的 Java 版本低於 1.8,也建議參考該指南。
4. 配置
為了啓動 FlexyPool,我們首先需要一個 <em >FlexyPoolDataSource</em> 數據源。它需要一個特定於連接池的數據庫連接數據源,在本例中是 <em >HikariDataSource</em> 數據源。 讓我們一起設置它們。
4.1. HikariDataSource 配置
首先,我們使用內存中的 H2 數據庫配置 HikariDataSource:
@Bean
public HikariDataSource hikariDataSource() {
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;INIT=runscript from 'classpath:/db.sql'");
config.setUsername("");
config.setPassword("");
config.addDataSourceProperty("cachePrepStmts", "true");
config.addDataSourceProperty("prepStmtCacheSize", "250");
config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
config.addDataSourceProperty("minimumPoolSize", "1");
config.addDataSourceProperty("maximumPoolSize", "3");
config.addDataSourceProperty("connectionTimeout", "1000");
return new HikariDataSource(config);
}在這裏,我們添加了 maximumPoolSize 和 connectionTimeout 屬性。 如前所述,它們對 FlexyPool 的 IncrementPoolOnTimeoutConnectionAcquiringStrategy 有用。
接下來,我們使用 HikariDataSource 編排一個配置 Bean:
@Bean
public Configuration<HikariDataSource> flexypoolConfiguration() {
HikariDataSource dataSource = hikariDataSource();
return new Configuration.Builder<>(UUID.randomUUID().toString(), dataSource, HikariCPPoolAdapter.FACTORY)
.setMetricsFactory(MicrometerMetrics::new)
.setConnectionProxyFactory(ConnectionDecoratorFactoryResolver.INSTANCE.resolve())
.setMetricLogReporterMillis(TimeUnit.SECONDS.toMillis(5))
.setMetricNamingUniqueName(UniqueNamingStrategy.INSTANCE)
.setJmxEnabled(true)
.setJmxAutoStart(true)
.setConnectionAcquireTimeThresholdMillis(50L)
.setConnectionLeaseTimeThresholdMillis(250L)
.setEventListenerResolver(() -> Arrays.asList(
new ConnectionAcquireTimeoutEventListener(),
new ConnectionAcquireTimeThresholdExceededEventListener(),
new ConnectionLeaseTimeThresholdExceededEventListener()))
.build();
}此配置:
- 啓用 JMX 報告
- 將指標實現設置為 Micrometer。 Micrometer 適配器默認使用 SimpleMetricsRegistry。 但是,它可以自定義使用集成監控報告工具,例如 Ganglia 和 Graphite。
- 添加監聽器到各種連接事件:ConnectionAcquireTimeoutEvent、ConnectionAcquireTimeThresholdExceededEvent 和 ConnectionLeaseTimeThresholdExceeded。 值得注意的是,這些監聽器是同步的,因此不應執行耗時的任務。
- 將連接租期設置為 250 毫秒
- 將連接獲取時間設置為 50 毫秒
4.2. FlexyPoolDataSource 配置
讓我們配置一個 FlexyPoolDataSource Bean:
@Bean(initMethod = "start", destroyMethod = "stop")
public FlexyPoolDataSource<HikariDataSource> flexypoolDataSource() {
Configuration<HikariDataSource> configuration = flexypoolConfiguration();
return new FlexyPoolDataSource<>(
configuration,
new IncrementPoolOnTimeoutConnectionAcquiringStrategy.Factory<>(5),
new RetryConnectionAcquiringStrategy.Factory<>(2));
}該 FlexyPoolDataSource 在連接超時時,向 Hikari 池添加五個額外的連接。它還會在池無法檢索連接時最多重試兩次連接。
最後,我們可以通過調用 FlexyPoolDataSource 運行我們的應用程序。
@SpringBootApplication
public class FlexypoolDemoApplication {
private static FlexyPoolDataSource<HikariDataSource> poolDataSource;
public FlexypoolDemoApplication(FlexyPoolDataSource<HikariDataSource> poolDataSource) {
FlexypoolDemoApplication.poolDataSource = poolDataSource;
}
public static List<Employee> getEmployees() throws SQLException {
String SQL_QUERY = "select * from emp";
List<Employee> employees;
try (Connection con = poolDataSource.getConnection(); PreparedStatement pst = con.prepareStatement(SQL_QUERY); ResultSet rs = pst.executeQuery();) {
employees = new ArrayList<>();
Employee employee;
while (rs.next()) {
employee = new Employee();
employee.setEmpNo(rs.getInt("empno"));
employee.setEname(rs.getString("ename"));
employee.setJob(rs.getString("job"));
employee.setMgr(rs.getInt("mgr"));
employee.setHiredate(rs.getDate("hiredate"));
employee.setSal(rs.getInt("sal"));
employee.setComm(rs.getInt("comm"));
employee.setDeptno(rs.getInt("deptno"));
employees.add(employee);
}
}
return employees;
}
public static void main(String[] args) throws SQLException {
SpringApplication.run(FlexypoolDemoApplication.class, args);
List<Employee> employees = getEmployees();
System.out.println(employees);
}
}5. 結論
在本文中,我們學習瞭如何使用 FlexyPool 與 Spring Boot 和 H2 結合,並使用 HikariCP 連接池。
首先,我們瞭解瞭如何設置 FlexyPool 並進行配置。然後,我們還了解了如何監控其指標。