r2dbc / r2dbc-pool

Connection Pooling for Reactive Relational Database Connectivity
https://r2dbc.io
Apache License 2.0
331 stars 55 forks source link

R2DBC Pool does not guarantee minIdle #200

Open pkgonan opened 10 months ago

pkgonan commented 10 months ago

Bug Report

First, Error Detected

CannotCreateTransactionException
Could not open R2DBC Connection for transaction
스크린샷 2023-10-29 오후 11 42 45 스크린샷 2023-10-29 오후 11 42 58

Second, We found R2DBC Pool Status Oddly enough, there is no guarantee of R2DBC Pool minIdle on a particular instance. The number of R2DBC Pool idle connections is not being maintained.

Only 1 out of 3 instances is anomalous. Please check the image below.

스크린샷 2023-10-29 오후 11 18 47

Third, Source Code

@Configuration
internal class R2dbcConfiguration internal constructor(
    @Value("\${payment-platform.r2dbc.host}")
    private val host: String,
    @Value("\${payment-platform.r2dbc.port}")
    private val port: Int,
    @Value("\${payment-platform.r2dbc.username}")
    private val username: String,
    @Value("\${payment-platform.r2dbc.password}")
    private val password: String,
    @Value("\${payment-platform.r2dbc.database}")
    private val database: String,
): AbstractR2dbcConfiguration() {

    companion object {
        const val CONNECTION_FACTORY_PROVIDER_DRIVER_NAME = MariadbConnectionFactoryProvider.MARIADB_DRIVER

        private const val MAX_SIZE = 20
        private const val INITIAL_SIZE = MAX_SIZE
        private val CONNECTION_POOL_MAX_LIFE_TIME = Duration.ofSeconds(30)
    }

    @Bean
    override fun connectionFactory(): ConnectionFactory {
        return ConnectionFactories.get(
            ConnectionFactoryOptions.builder()
                .option(ConnectionFactoryOptions.SSL, false)
                .option(ConnectionFactoryOptions.HOST, host)
                .option(ConnectionFactoryOptions.PORT, port)
                .option(ConnectionFactoryOptions.USER, username)
                .option(ConnectionFactoryOptions.PASSWORD, password)
                .option(ConnectionFactoryOptions.DATABASE, database)
                .option(ConnectionFactoryOptions.DRIVER, PoolingConnectionFactoryProvider.POOLING_DRIVER)
                .option(ConnectionFactoryOptions.PROTOCOL, CONNECTION_FACTORY_PROVIDER_DRIVER_NAME)
                .option(PoolingConnectionFactoryProvider.INITIAL_SIZE, INITIAL_SIZE)
                .option(PoolingConnectionFactoryProvider.MAX_SIZE, MAX_SIZE)
                .option(PoolingConnectionFactoryProvider.MIN_IDLE, MAX_SIZE / 2)
                .option(PoolingConnectionFactoryProvider.MAX_ACQUIRE_TIME, Duration.ofSeconds(2))
                .option(PoolingConnectionFactoryProvider.MAX_CREATE_CONNECTION_TIME, Duration.ofSeconds(2))
                .option(PoolingConnectionFactoryProvider.MAX_LIFE_TIME, CONNECTION_POOL_MAX_LIFE_TIME)
                .option(PoolingConnectionFactoryProvider.VALIDATION_DEPTH, ValidationDepth.REMOTE)
                .option(PoolingConnectionFactoryProvider.MAX_VALIDATION_TIME, Duration.ofSeconds(2))
                .option(MariadbConnectionFactoryProvider.LOOP_RESOURCES, LoopResources.create("r2dbc", LoopResources.DEFAULT_IO_SELECT_COUNT, LoopResources.DEFAULT_IO_WORKER_COUNT, true, false))
                .build()
        )
    }
}

Versions

pkgonan commented 10 months ago

@mp911de @pderop Hi.

Do you know about this issue?

I would appreciate any suggestions on how to fix it.

pderop commented 10 months ago

@pkgonan ,

Hi,

Thank you for reaching out, but I'm unsure how I can help here, so I will let @mp911de comment on this issue. If you suspect that the problem may be related to the reactor-pool project, I'd recommend isolating the issue there first and, if needed, submit a separate issue in the reactor-pool GH project with the details.

Thank you.

mp911de commented 10 months ago

MinIdle is being considered upon connection pool warmup. Is your application calling ConnectionPool.warmup() and awaiting the result?

Regarding the exception, can you attach the stack trace so that we can direct the issue into the appropriate component?