首页 > 解决方案 > Spring Boot JPA 多租户 HikariCP 池快速运行满

问题描述

我有一个 Spring Boot - JPA - Postgres 多租户设置,其中每个租户都在一个单独的模式中。直到今天,当我尝试创建超过 5 个租户时,一切都运行良好。不,我在启动时遇到了这个异常:

java.sql.SQLTransientConnectionException: HikariPool-1 - Connection is not available, request timed out after 30003ms

我的 Hikari CP 最大大小为 5。我在 DEBUG 日志中有 Hikari,日志说:

HikariPool-1 - Pool stats (total=5, active=5, idle=0, waiting=0)

据我了解,Hikari 无法释放到不同模式的连接,所以我最终遇到了这个错误。

我的多租户连接提供商是这样的:

@Component
class MultiTenantConnectionProviderImpl(private val dataSource: DataSource) : MultiTenantConnectionProvider {

    override fun getAnyConnection(): Connection {
        return dataSource.connection
    }

    override fun releaseAnyConnection(connection: Connection) {
        connection.close()
    }

    override fun getConnection(tenantIdentifier: String): Connection {
        val connection = anyConnection
        try {
            connection.schema = tenantIdentifier
        } catch (e: SQLException) {
            throw HibernateException(
                "Could not alter JDBC connection to specified schema [$tenantIdentifier]", e
            )
        }

        return connection
    }

    override fun releaseConnection(tenantIdentifier: String, connection: Connection) {
        try {
            connection.schema = null
        } catch (e: SQLException) {
            throw HibernateException(
                "Could not alter JDBC connection to null schema", e
            )
        }

        connection.close()
    }

    override fun isUnwrappableAs(unwrapType: Class<*>): Boolean {
        return false
    }

    override fun <T> unwrap(unwrapType: Class<T>): T? {
        return null
    }

    override fun supportsAggressiveRelease(): Boolean {
        return true
    }
}

如果我将调试器设置为 on releaseConnection,它永远不会去那里。它去了一次,releaseAnyConnection但实际上并没有将连接从活动连接中移开。

所以现在我被困在这里,有点不知道如何继续前进。

如果我向每个租户提出了至少一个请求,则会发生此异常。问题是,当我的应用程序启动时,它会从配置模式中查询所有租户模式名称,然后针对所有这些模式(在循环中)执行 Liquibase 脚本,以确保所有租户模式都是最新的。因此,在启动后,如果我的租户数量多于连接池允许的最大连接数,我肯定会面临这种异常情况。我可以从这个应用程序中删除模式更新,但我仍然希望有数百个同时登录到我的应用程序的租户,所以迟早我仍然会遇到这个问题。通过谷歌搜索,我发现有些人遇到了这个问题,因为他们的查询运行了很长时间,但与多租户无关。

我的应用程序.yml:

spring:
  jpa:
    hibernate.ddl-auto: none
    properties.hibernate.jdbc.lob.non_contextual_creation: true
    database-platform: org.hibernate.dialect.PostgreSQL9Dialect
  datasource:
    jdbcUrl: jdbc:postgresql://localhost:5432/mydb
    username: mydb
    password: mydb
    driverClassName: org.postgresql.Driver
    type: com.zaxxer.hikari.HikariDataSource
    maximumPoolSize: 5

Spring Boot 版本为 2.0.5.RELEASE 和 Hikari 2.7.9

标签: kotlinmulti-tenanthikaricpspring-boot-jpa

解决方案


推荐阅读