R2DBC 池在每次查询前关闭所有连接
R2DBC pool closes all connections before each query
我们使用最新版本的 spring-data-r2dbc
、r2dbc-pool
和 r2dbc-postgresql
通过连接池连接到 PostgreSQL 数据库。我们注意到一些高响应时间,远高于从数据库本身获取的查询响应时间 (query_store.qs_view
)
我们向池中添加了一个 metricsRecorder
,出于调试目的,我们仅在调用每个方法时才打印。似乎在每个 SQL 查询之前,我们得到与池中连接数一样多的 recordDestroyLatency
调用和相同数量的 recordAllocationSuccessAndLatency
调用。我们假设这意味着每个连接在每次查询之前都会关闭并重新打开。然后我们与数据库日志进行了比较,结果证明这是真的:could not receive data from client: An existing connection was forcibly closed by the remote host
后跟 connection received:
条消息的数量相同。
为什么会这样?下面是我们用于创建连接工厂的代码。
@Configuration
open class DatabaseConfiguration : AbstractR2dbcConfiguration() {
//some variable initialisations
@Bean
override fun connectionFactory(): ConnectionFactory {
val cf = PostgresqlConnectionFactory(
PostgresqlConnectionConfiguration.builder()
.host(hostname)
.database(dbName)
.schema(dbSchema)
.username(dbUsername)
.password(dbPassword)
.build()
)
val cp = ConnectionPoolConfiguration.builder(cf)
.initialSize(poolInitialSize)
.maxSize(poolMaxSize)
.metricsRecorder(DatabaseMetricsRecorder())
.build()
return ConnectionPool(cp)
}
}
如前所述,DatabaseMetricsRecorder
仅打印每个操作。对于查询本身,我们正在扩展 ReactiveCrudRepository
接口。 ConnectionPoolConfiguration
在这里是最简单的形式,我们尝试添加像 maxIdleTime
或 validationQuery
这样的参数(因为我们将在生产中使用)但它似乎没有帮助。
这是 R2DBC 池中的一个已知错误,这里是 issue。作为解决方法,应该明确设置 maxLifeTime
,例如我将其设置为以毫秒为单位的最大允许值(否则,如果设置为大于以毫秒为单位的最大允许值的值,R2DBC 将抛出异常):
val cp = ConnectionPoolConfiguration.builder(cf)
.initialSize(poolInitialSize)
.maxSize(poolMaxSize)
.maxLifeTime(Duration.ofMillis(Long.MAX_VALUE))
.metricsRecorder(DatabaseMetricsRecorder())
.build()
我们使用最新版本的 spring-data-r2dbc
、r2dbc-pool
和 r2dbc-postgresql
通过连接池连接到 PostgreSQL 数据库。我们注意到一些高响应时间,远高于从数据库本身获取的查询响应时间 (query_store.qs_view
)
我们向池中添加了一个 metricsRecorder
,出于调试目的,我们仅在调用每个方法时才打印。似乎在每个 SQL 查询之前,我们得到与池中连接数一样多的 recordDestroyLatency
调用和相同数量的 recordAllocationSuccessAndLatency
调用。我们假设这意味着每个连接在每次查询之前都会关闭并重新打开。然后我们与数据库日志进行了比较,结果证明这是真的:could not receive data from client: An existing connection was forcibly closed by the remote host
后跟 connection received:
条消息的数量相同。
为什么会这样?下面是我们用于创建连接工厂的代码。
@Configuration
open class DatabaseConfiguration : AbstractR2dbcConfiguration() {
//some variable initialisations
@Bean
override fun connectionFactory(): ConnectionFactory {
val cf = PostgresqlConnectionFactory(
PostgresqlConnectionConfiguration.builder()
.host(hostname)
.database(dbName)
.schema(dbSchema)
.username(dbUsername)
.password(dbPassword)
.build()
)
val cp = ConnectionPoolConfiguration.builder(cf)
.initialSize(poolInitialSize)
.maxSize(poolMaxSize)
.metricsRecorder(DatabaseMetricsRecorder())
.build()
return ConnectionPool(cp)
}
}
如前所述,DatabaseMetricsRecorder
仅打印每个操作。对于查询本身,我们正在扩展 ReactiveCrudRepository
接口。 ConnectionPoolConfiguration
在这里是最简单的形式,我们尝试添加像 maxIdleTime
或 validationQuery
这样的参数(因为我们将在生产中使用)但它似乎没有帮助。
这是 R2DBC 池中的一个已知错误,这里是 issue。作为解决方法,应该明确设置 maxLifeTime
,例如我将其设置为以毫秒为单位的最大允许值(否则,如果设置为大于以毫秒为单位的最大允许值的值,R2DBC 将抛出异常):
val cp = ConnectionPoolConfiguration.builder(cf)
.initialSize(poolInitialSize)
.maxSize(poolMaxSize)
.maxLifeTime(Duration.ofMillis(Long.MAX_VALUE))
.metricsRecorder(DatabaseMetricsRecorder())
.build()