多租户软件中的WildFly / JPA数据库连接泄漏

时间:2015-04-14 10:44:24

标签: hibernate postgresql jpa

我想为我们的Java EE软件使用多租户架构。 我们使用WildFly 8.2(带有Hibernate 4.3.7的JPA)和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>

2 个答案:

答案 0 :(得分:0)

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

解决步骤

  1. 查找保持连接打开的查询:由于您使用的是postgres,请使用此查询查找哪个查询保持连接打开。如果您发现查询半工作已完成。
  2.   

    SELECT datname,pid,usename,waiting,state,(now() - query_start)AS   因为,(now() - state_change)AS since2,(now() - backend_start)as   since3,(now() - xact_start)as4,查询FROM pg_stat_activity   自订单开始;

    1. 配置wildfly以释放连接:启用idle-time-out
    2. B

      同时定义刷新策略

      <timeout><idle-timeout-minutes>1</idle-timeout-minutes></timeout>
      

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

      如果你能够使用http://www.mastertheboss.com/jbossas/wildfly9/detecting-connection-leaks-in-wildfly-9

      ,你可以找到它

答案 1 :(得分:0)

@Override
public boolean supportsAggressiveRelease() {
    return true; // changing this true from false will fix the leak.
}