反应式Spring Boot服务中AWS RDS连接闲置后无法自动重连问题
基于反应式Spring Boot搭建的服务,负责接收SQS消息并处理。遇到的问题:当队列为空、应用闲置一段时间后,AWS RDS的数据库连接会被关闭;队列再次收到消息时,应用能正常接收消息,但无法重新初始化RDS连接。
用到的数据库依赖:
jasync-r2dbc-mysql:2.0.0 spring-boot-starter-data-r2dbc:2.3.0.M3 spring-boot-starter-data-jpa:2.3.0.M3 mysql-connector-java:8.0.26
数据库连接池配置:
ConnectionPoolConfiguration configuration = ConnectionPoolConfiguration.builder(connectionFactory) .maxIdleTime(Duration.ofHours(10)) // max idle time for a connection .maxSize(50) .maxLifeTime(Duration.ofMillis(Long.MAX_VALUE)) .metricsRecorder(new SimplePoolMetricsRecorder()) .minIdle(5) .validationQuery(validationQuery) .initialSize(5) .build();
日志表现:
连接释放后,没有任何获取连接的日志输出
期望:应用闲置后收到消息时,能自动重新获取可用的数据库连接。
1. 修正maxLifeTime配置
你把连接的最大生命周期设为Long.MAX_VALUE,意味着连接永远不会被连接池主动回收。但AWS RDS默认会关闭闲置超过8小时的连接,这就造成池里的连接已经被RDS端销毁,但池还以为它们可用,导致后续拿不到有效连接。
把maxLifeTime改成小于RDS闲置超时的数值,比如7小时:
.maxLifeTime(Duration.ofHours(7))
2. 确保连接借出时自动校验
虽然配置了validationQuery,但默认可能没开启借出时校验。添加以下配置,让连接池在借出连接前自动校验有效性,失效的话会自动创建新连接:
.validationQuery(validationQuery) .validationTimeout(Duration.ofSeconds(5)) .validateOnBorrow(true)
3. 清理冲突依赖
同时引入spring-boot-starter-data-jpa(阻塞式JDBC持久化)和spring-boot-starter-data-r2dbc(反应式持久化)会导致连接池管理冲突。如果是纯反应式服务,直接移除spring-boot-starter-data-jpa和mysql-connector-java,只保留R2DBC相关依赖。
4. 调整maxIdleTime配置
当前maxIdleTime设为10小时,超过了RDS默认的8小时闲置超时,会导致池里的闲置连接被RDS提前关闭。改成7小时:
.maxIdleTime(Duration.ofHours(7))
5. 开启连接池日志排查
开启R2DBC连接池的DEBUG日志,方便追踪连接的获取、回收和校验流程,在application.yml中添加:
logging: level: io.r2dbc.pool: DEBUG
验证:调整配置后,让应用闲置超过7小时,再发送SQS消息,观察是否能正常处理,同时查看日志确认连接是否被正确校验和重建。
内容的提问来源于stack exchange,提问作者Satyam Pandey

