我已经开始将现有的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并崩溃。
你们有什么主意吗?
谢谢, 凯伦