整合agroal
本文介绍如何在 tio-boot 项目中使用 Agroal 连接池 作为数据源,并与 jOOQ 集成,同时提供事务管理能力。
该方案具有以下特点:
- 无 Spring 依赖
- 程序化配置(对 AOT / Native 更友好)
- 启动路径清晰
- 易于控制生命周期
- 性能稳定
适用于:
- 高性能 REST / RPC 服务
- AOT / GraalVM 方向项目
- 不希望引入重量级框架的系统
一、依赖配置
添加 Agroal 连接池:
<dependency>
<groupId>io.agroal</groupId>
<artifactId>agroal-pool</artifactId>
<version>3.0</version>
</dependency>
同时确保已引入:
- PostgreSQL Driver(或你的数据库驱动)
- jOOQ
例如:
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.2.24</version>
</dependency>
二、整体架构说明
启动时完成以下初始化流程:
- 读取数据库配置
- 构建 Agroal ConnectionFactory
- 配置连接池参数
- 创建 DataSource
- 初始化 jOOQ DSLContext
- 注册事务管理器
- 注入 AOP 容器
- 在 JVM 关闭时优雅释放连接池
三、完整配置示例
package demo.jooq.config;
import java.sql.SQLException;
import java.time.Duration;
import javax.sql.DataSource;
import org.jooq.DSLContext;
import org.jooq.SQLDialect;
import org.jooq.impl.DSL;
import com.litongjava.annotation.AConfiguration;
import com.litongjava.annotation.Initialization;
import com.litongjava.constants.ServerConfigKeys;
import com.litongjava.hook.HookCan;
import com.litongjava.jfinal.aop.AopManager;
import com.litongjava.tio.utils.environment.EnvUtils;
import demo.jooq.tx.TransactionManager;
import io.agroal.api.AgroalDataSource;
import io.agroal.api.configuration.supplier.AgroalConnectionFactoryConfigurationSupplier;
import io.agroal.api.configuration.supplier.AgroalConnectionPoolConfigurationSupplier;
import io.agroal.api.configuration.supplier.AgroalDataSourceConfigurationSupplier;
import io.agroal.api.security.NamePrincipal;
import io.agroal.api.security.SimplePassword;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@AConfiguration
public class JooqConfig {
@Initialization
public void initJooq() throws SQLException {
// 读取数据库配置
String jdbcUrl = EnvUtils.get(ServerConfigKeys.JDBC_URL);
String username = EnvUtils.getStr(ServerConfigKeys.JDBC_USER);
String password = EnvUtils.getStr(ServerConfigKeys.JDBC_PSWD);
/**
* 1. 连接工厂配置
* 明确指定 Driver,有助于 AOT / Native 编译
*/
AgroalConnectionFactoryConfigurationSupplier connectionFactory =
new AgroalConnectionFactoryConfigurationSupplier()
.connectionProviderClass(org.postgresql.Driver.class)
.jdbcUrl(jdbcUrl)
.principal(new NamePrincipal(username))
.credential(new SimplePassword(password));
/**
* 2. 连接池配置
*/
AgroalConnectionPoolConfigurationSupplier poolConfig =
new AgroalConnectionPoolConfigurationSupplier()
.connectionFactoryConfiguration(connectionFactory)
.minSize(0)
.maxSize(20)
.acquisitionTimeout(Duration.ofSeconds(30))
.maxLifetime(Duration.ofMinutes(30));
/**
* 3. 创建 DataSource
*/
AgroalDataSourceConfigurationSupplier dsConfig =
new AgroalDataSourceConfigurationSupplier()
.connectionPoolConfiguration(poolConfig)
.metricsEnabled(true);
AgroalDataSource agroalDataSource = AgroalDataSource.from(dsConfig);
/**
* 4. 初始化 jOOQ
*/
DSLContext dslContext =
DSL.using((DataSource) agroalDataSource, SQLDialect.POSTGRES);
/**
* 5. 注册单例
*/
AopManager.me().addSingletonObject(AgroalDataSource.class, agroalDataSource);
AopManager.me().addSingletonObject(DSLContext.class, dslContext);
/**
* 6. 注册事务管理器
*/
TransactionManager txManager =
new TransactionManager(agroalDataSource, SQLDialect.POSTGRES);
AopManager.me().addSingletonObject(TransactionManager.class, txManager);
log.info("jOOQ + Agroal initialized");
/**
* 7. 优雅关闭连接池
*/
HookCan.me().addDestroyMethod(() -> {
try {
agroalDataSource.close();
log.info("AgroalDataSource closed");
} catch (Exception e) {
log.warn("Failed to close AgroalDataSource", e);
}
});
}
}
四、关键设计说明
1. 为什么推荐程序化配置?
优点:
- 避免反射
- 避免 XML / SPI 扫描
- 对 GraalVM 更友好
- 初始化路径可控
如果未来考虑:
- Native Image
- Serverless
- 极速冷启动
这种方式非常推荐。
2. 为什么要显式指定 Driver?
强烈建议:
.connectionProviderClass(org.postgresql.Driver.class)
原因:
在 AOT / Native 编译中:
- DriverManager 自动发现可能失效
- ServiceLoader 可能被裁剪
显式声明最安全。
3. minSize = 0 是否合理?
推荐策略:
中低流量系统
minSize = 0
降低空闲连接成本。
高频系统
minSize = CPU核心数 或 10+
减少冷连接延迟。
4. maxSize 如何设置?
一个常见经验公式:
maxSize ≈ (CPU核心数 * 2) + 有效磁盘数
但更重要的是:
不要超过数据库允许连接数。
例如:
PostgreSQL 默认:
max_connections = 100
你的应用池最好:
10 ~ 30
而不是 80。
五、Agroal vs 常见连接池
推荐程度:
如果目标是 AOT / Native:
首选:
Agroal
如果只追求极致 micro-benchmark:
HikariCP
但在真实业务中:
SQL、锁、网络远比连接池更影响性能。
差距通常小于 2%。
六、常见问题
Q:Agroal 性能如何?
非常高。
在现代连接池中属于第一梯队。
通常瓶颈不会在连接池。
Q:是否适合高并发?
完全适合。
Quarkus 默认连接池就是它。
Q:是否支持 Native?
是的,而且设计目标之一就是支持云原生运行环境。
七、建议的生产配置
推荐起步值:
minSize = 2~5
maxSize = 20~40
acquisitionTimeout = 5~10秒
maxLifetime = 20~30分钟
再根据:
- TPS
- SQL耗时
- DB CPU
逐步压测调整。
总结
该方案实现了:
- tio-boot + jOOQ
- 高性能连接池
- 可控生命周期
- 对 AOT 友好
- 无框架绑定
