Мультитенантный пул Spring Boot JPA HikariCP работает быстро - PullRequest
0 голосов
/ 08 апреля 2019

У меня есть установка для нескольких арендаторов Spring Boot - JPA - Postgres, где каждый арендатор находится в отдельной схеме. Все работало нормально до сегодняшнего дня, когда я попытался создать более 5 арендаторов. Нет, я получаю это исключение при запуске:

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

Максимальный размер моего Hikari CP - 5. У меня есть Hikari в журнале DEBUG, и в журналах написано:

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
    }
}

Если я установлю свой отладчик на releaseConnection, он никогда не пойдет туда. Один раз он переходит к releaseAnyConnection, но это фактически не удаляет соединение от активных соединений.

Так что теперь я застрял здесь и немного не знаю, как двигаться к этому.

Это исключение происходит, если я сделал по крайней мере один запрос с каждым арендатором. Проблема заключается в том, что когда мое приложение запускается, оно запрашивает все имена схем арендаторов из схемы конфигурации, а затем выполняет сценарии Liquibase для всех этих схем (в цикле), чтобы убедиться, что все схемы арендаторов обновлены. Таким образом, после запуска я гарантированно окажусь в ситуации, с которой столкнется это исключение, если у меня будет больше арендаторов, чем у пула соединений максимально допустимые соединения. Я мог бы удалить обновления схемы из этого приложения, но, тем не менее, я ожидал, что в мое приложение одновременно войдут сотни одновременных клиентов, поэтому рано или поздно я все равно столкнусь с этой проблемой. Путем поиска в Google я нашел некоторых людей, у которых была эта проблема, потому что у них есть запросы, которые выполняются в течение очень долгого времени, но ничего не связано с мульти-арендой.

My application.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 2.0.5. ВЫПУСК и Hikari 2.7.9

...