Spring Boot LocalContainerEntityManagerFactoryBean不关闭连接

时间:2019-01-21 13:10:00

标签: hibernate spring-boot database-connection connection-pooling multi-tenant

我已经开始将现有的Spring Boot(1.5.4.RELEASE)应用程序转换为可使用多租户功能。这是一个基于架构的多租户解决方案,基于mysql。正如下面建议的休眠文件

https://docs.jboss.org/hibernate/orm/4.2/devguide/en-US/html/ch16.html

我已经实现了MultiTenantConnectionProvider和CurrentTenantIdentifierResolver接口,并且运行良好,下面是我的休眠配置

@Configuration
public class HibernateConfig {

  @Autowired
  private JpaProperties jpaProperties;

  @Bean
  public JpaVendorAdapter jpaVendorAdapter() {
    return new HibernateJpaVendorAdapter();
  }

  @Bean
  public LocalContainerEntityManagerFactoryBean 
    entityManagerFactory(DataSource dataSource,
    MultiTenantConnectionProvider multiTenantConnectionProviderImpl,
    CurrentTenantIdentifierResolver currentTenantIdentifierResolverImpl) {
     Map<String, Object> properties = new HashMap<>();
     properties.putAll(jpaProperties.getHibernateProperties(dataSource));
     properties.put(Environment.MULTI_TENANT, MultiTenancyStrategy.SCHEMA);
     properties.put(Environment.MULTI_TENANT_CONNECTION_PROVIDER, multiTenantConnectionProviderImpl);
     properties.put(Environment.MULTI_TENANT_IDENTIFIER_RESOLVER, currentTenantIdentifierResolverImpl);

     LocalContainerEntityManagerFactoryBean em = new 
             LocalContainerEntityManagerFactoryBean();
     em.setDataSource(dataSource);
     em.setPackagesToScan("com.ifi.aws");
     em.setJpaVendorAdapter(jpaVendorAdapter());
     em.setJpaPropertyMap(properties);
    return em;
 }
}

后来我开始测试时,它开始失败并出现以下错误

带有MultiTenantConnectionProvider的Springboot多租户总是抛出org.apache.tomcat.jdbc.pool.PoolExhaustedException:[http-nio-8086-exec-2]超时:池为空。 30秒内无法获取连接,无可用[size:100;繁忙:100;空闲:0; lastwait:30000]。

我做了一些背景阅读,它建议对“ after_transaction”使用hibernate.connection.release_mode,但是没有用。然后有另一篇文章,它告诉我们,由于我是从Entity Manager Factory中创建一个新的Entity Manager的,Spring不再对此进行管理。

https://github.com/brettwooldridge/HikariCP/issues/1238

为了检查连接泄漏,我只写了一个带有方面的简单类。

Aspect

@Component 公共类DataSourceAspectLogger {

protected final Logger logger = LoggerFactory.getLogger(this.getClass());

@Autowired
private DataSource ds;

@Before("execution(* com.ifi.aws.*.dao.impl.springData.*.*(..))")
public void logBeforeConnection(JoinPoint jp) throws Throwable {
    logDataSourceInfos("Before", jp);
}

@After("execution(* com.ifi.aws.*.dao.impl.springData.*.*(..)) ")
public void logAfterConnection(JoinPoint jp) throws Throwable {
    logDataSourceInfos("After", jp);
}

public void logDataSourceInfos(final String time, final JoinPoint jp) {
    final String method = String.format("%s:%s", jp.getTarget().getClass().getName(), jp.getSignature().getName());
    logger.debug("--------------------------------------------------------------------------");
    logger.debug(String.format("%s %s: number of connections in use by the application (active): %d.", time, method, ds.getNumActive()));
    logger.debug(String.format("%s %s: the number of established but idle connections: %d.", time, method, ds.getNumIdle()));
    logger.debug(String.format("%s %s: number of threads waiting for a connection: %d.", time, method, ds.getWaitCount()));
}

}

结果如下所示

After com.sun.proxy.$Proxy125:findByUserName: number of connections in use by the application (active): 12.
After com.sun.proxy.$Proxy125:findByUserName: the number of established but idle connections: 0.
After com.sun.proxy.$Proxy125:findByUserName: number of threads waiting for a connection: 0.

并不断增加活动连接数,直到达到该池的最大活动连接数100并崩溃。

你们有什么主意吗?

谢谢, 凯伦

0 个答案:

没有答案