【问题标题】:WildFly/JPA database connection leak in multitenant software多租户软件中的 WildFly/JPA 数据库连接泄漏
【发布时间】:2015-06-19 22:41:02
【问题描述】:

我想为我们的 Java EE 软件使用多租户架构。 我们使用 WildFly 8.2(JPA 和 Hibernate 4.3.7)和 PostgreSQL 9.3

我知道 Hibernate 为多租户提供了一些 API:http://docs.jboss.org/hibernate/orm/4.2/devguide/en-US/html/ch16.html

我们可以将它与 JPA 集成到 persistence.xml 文件中,如下所示:

<property name="hibernate.multiTenancy" value="SCHEMA"/>
<property name="hibernate.tenant_identifier_resolver" value="mycompany.hibernate.multitenant.SchemaResolver"/>
<property name="hibernate.multi_tenant_connection_provider" value="mycompany.hibernate.multitenant.MultiTenantProvider"/>

但是我的“hibernate.multi_tenant_connection_provider”有一些问题。

我想使用 WildFly 配置 (standalone.xml) 中的数据源池,但如果我使用它,它会导致池中的连接泄漏。 连接永远不会释放到池中。

我需要使用另一个库来管理我的数据库连接池,比如 C3P0 吗?我认为 WildFly 可以正确管理它。 有没有更好的方法将多租户与 JPA 集成?

或者我的 JNDI 查找有问题?

如果我使用 SCHEMA 进行多租户配置,连接总是到同一个数据库/数据源,那么为什么我们需要编写一些连接提供程序?

你有什么想法吗? 提前感谢您的帮助。

public class MultiTenantProvider implements MultiTenantConnectionProvider {

@Override
public boolean supportsAggressiveRelease() {
    return false;
}

@Override
public boolean isUnwrappableAs(Class clazz) {
    return false;
}

@Override
public <T> T unwrap(Class<T> clazz) {
    return null;
}

@Override
public Connection getAnyConnection() throws SQLException {
    Context initContext;
    Connection connection = null;
    try {
        initContext = new InitialContext();
        DataSource ds = (DataSource) initContext.lookup("java:/MyPostgresDS");
        connection = ds.getConnection();
    } catch (NamingException e) {
        e.printStackTrace();
    }
    return connection;
}

@Override
public Connection getConnection(String tenantIdentifier) throws SQLException {
    final Connection connection = getAnyConnection();
    try {
        connection.createStatement().execute("SET SCHEMA '" + tenantIdentifier + "'");
    }
    catch (SQLException e) {
        throw new HibernateException("Could not alter JDBC connection to specified schema [" + tenantIdentifier + "]", e);
    }
    return connection;
}

@Override
public void releaseAnyConnection(Connection connection) throws SQLException {
    try {
        connection.createStatement().execute("SET SCHEMA 'public'");
    }
    catch (SQLException e) {
        throw new HibernateException("Could not alter JDBC connection to specified schema [public]", e);
    }
    connection.close();
}

@Override
public void releaseConnection(String tenantIdentifier, Connection connection) throws SQLException {
    releaseAnyConnection(connection);
}

}

WildFly的standalone.xml文件中的数据源

<datasource jndi-name="java:/MyPostgresDS" pool-name="MyPostgresDS" enabled="true" use-java-context="true">
                <connection-url>jdbc:postgresql:demo</connection-url>
                <driver>posgresqlDriver</driver>
                <pool>
                    <min-pool-size>10</min-pool-size>
                    <max-pool-size>50</max-pool-size>
                    <prefill>true</prefill>
                </pool>
                <security>
                    <user-name>postgres</user-name>
                    <password>postgres</password>
                </security>
                <timeout>
                    <blocking-timeout-millis>20000</blocking-timeout-millis>
                    <idle-timeout-minutes>5</idle-timeout-minutes>
                </timeout>
            </datasource>

【问题讨论】:

  • 没人能帮我解决这个问题吗? :(

标签: hibernate postgresql jpa


【解决方案1】:

这个问题没有完美的解决方案。你需要尝试几件事。 Wildfly 无法正常释放空闲连接,如果它一直保持打开状态。

解决步骤

  1. 查找保持连接打开的查询:由于您使用的是 postgres,因此使用此查询来查找保持连接打开的查询。如果您发现查询完成了一半。

SELECT datname, pid, usename, waiting, state, (now()-query_start) AS 因为,(now() - state_change) AS since2,(now() - backend_start) as since3, (now() - xact_start) as since4, 从 pg_stat_activity 查询 从那时起订购;

  1. 配置 wildfly 以释放连接:启用空闲超时
<timeout><idle-timeout-minutes>1</idle-timeout-minutes></timeout>

同时定义刷新策略

<flush-strategy>IdleConnections</flush-strategy>

要记录 Wildfly 连接:http://www.javacodegeeks.com/2014/11/tomcat-wildfly-configuring-database-connectivity.html

如果您可以使用 wildfly 9,您可以使用 http://www.mastertheboss.com/jbossas/wildfly9/detecting-connection-leaks-in-wildfly-9 查找泄漏

【讨论】:

    【解决方案2】:
    @Override
    public boolean supportsAggressiveRelease() {
        return true; // changing this true from false will fix the leak.
    }
    

    【讨论】:

      最近更新 更多