我在Spring启动应用程序中使用DynamicRoutingDataSourceResolver连接到6个不同的数据源以及JDBCTemplate。 但是,在使用100个或更多线程进行负载测试时,我得到一个Pool是空的错误。 由于JDBCTemplate管理自己的池,还有其他任何方法可以解决错误 注意:每个数据库查询大约需要3分钟才能完全执行 下面是堆栈跟踪和DAO&其他引用的类。
application.properties
oms.db.datasource1.url=jdbc:oracle:thin:@xxx.xxx.xxx
oms.db.datasource1.username=xxxx
oms.db.datasource1.password=xxxx
oms.db.datasource1.driver-class-name=oracle.jdbc.driver.OracleDriver
oms.db.datasource1.schema=xxx
(Muliple sources configured)
package com.att.first.oms.dataaccesslayer.config;
import java.util.HashMap;
import java.util.Map;
import org.apache.tomcat.jdbc.pool.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
@Configuration
public class DataSourceConfig {
@Autowired
private OMSSegmentProperties omsSegmentProperties;
@Bean
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource());
}
@Bean(name = "dataSource1")
@ConfigurationProperties(prefix = "oms.db.datasource1")
public DataSource dataSource1() {
String SET_DEFAULT_SCHEMA = "ALTER SESSION SET CURRENT_SCHEMA="
+ this.omsSegmentProperties.getDatasource1().getSchema().get(0);
DataSource ds = new DataSource();
ds.setDriverClassName(this.omsSegmentProperties.getDatasource1()
.getDriverClassName());
ds.setPassword(this.omsSegmentProperties.getDatasource1().getPassword());
ds.setUsername(this.omsSegmentProperties.getDatasource1().getUsername());
ds.setUrl(this.omsSegmentProperties.getDatasource1().getUrl());
ds.setInitSQL(SET_DEFAULT_SCHEMA);
return ds;
}
@Bean(name = "dataSource11")
@ConfigurationProperties(prefix = "oms.db.datasource1")
public DataSource dataSource11() {
String SET_DEFAULT_SCHEMA = "ALTER SESSION SET CURRENT_SCHEMA="
+ this.omsSegmentProperties.getDatasource1().getSchema().get(1);
DataSource ds = new DataSource();
ds.setDriverClassName(this.omsSegmentProperties.getDatasource1()
.getDriverClassName());
ds.setPassword(this.omsSegmentProperties.getDatasource1().getPassword());
ds.setUsername(this.omsSegmentProperties.getDatasource1().getUsername());
ds.setUrl(this.omsSegmentProperties.getDatasource1().getUrl());
ds.setInitSQL(SET_DEFAULT_SCHEMA);
return ds;
}
@Bean(name = "dataSource2")
@ConfigurationProperties(prefix = "oms.db.datasource2")
public DataSource dataSource2() {
String SET_DEFAULT_SCHEMA = "ALTER SESSION SET CURRENT_SCHEMA="
+ this.omsSegmentProperties.getDatasource2().getSchema().get(0);
DataSource ds = new DataSource();
ds.setDriverClassName(this.omsSegmentProperties.getDatasource2()
.getDriverClassName());
ds.setUsername(this.omsSegmentProperties.getDatasource2().getUsername());
ds.setPassword(this.omsSegmentProperties.getDatasource2().getPassword());
ds.setUrl(this.omsSegmentProperties.getDatasource2().getUrl());
ds.setInitSQL(SET_DEFAULT_SCHEMA);
return ds;
}
@Bean(name = "dataSource21")
@ConfigurationProperties(prefix = "oms.db.datasource2")
public DataSource dataSource21() {
String SET_DEFAULT_SCHEMA = "ALTER SESSION SET CURRENT_SCHEMA="
+ this.omsSegmentProperties.getDatasource2().getSchema().get(1);
DataSource ds = new DataSource();
ds.setDriverClassName(this.omsSegmentProperties.getDatasource2()
.getDriverClassName());
ds.setUsername(this.omsSegmentProperties.getDatasource2().getUsername());
ds.setPassword(this.omsSegmentProperties.getDatasource2().getPassword());
ds.setUrl(this.omsSegmentProperties.getDatasource2().getUrl());
ds.setInitSQL(SET_DEFAULT_SCHEMA);
return ds;
}
@Bean(name = "dataSource3")
@ConfigurationProperties(prefix = "oms.db.datasource3")
public DataSource dataSource3() {
String SET_DEFAULT_SCHEMA = "ALTER SESSION SET CURRENT_SCHEMA="
+ this.omsSegmentProperties.getDatasource3().getSchema().get(0);
DataSource ds = new DataSource();
ds.setDriverClassName(this.omsSegmentProperties.getDatasource3()
.getDriverClassName());
ds.setUsername(this.omsSegmentProperties.getDatasource3().getUsername());
ds.setPassword(this.omsSegmentProperties.getDatasource3().getPassword());
ds.setUrl(this.omsSegmentProperties.getDatasource3().getUrl());
ds.setInitSQL(SET_DEFAULT_SCHEMA);
return ds;
}
@Bean(name = "dataSource31")
@ConfigurationProperties(prefix = "oms.db.datasource3")
public DataSource dataSource31() {
String SET_DEFAULT_SCHEMA = "ALTER SESSION SET CURRENT_SCHEMA="
+ this.omsSegmentProperties.getDatasource3().getSchema().get(1);
DataSource ds = new DataSource();
ds.setDriverClassName(this.omsSegmentProperties.getDatasource3()
.getDriverClassName());
ds.setUsername(this.omsSegmentProperties.getDatasource3().getUsername());
ds.setPassword(this.omsSegmentProperties.getDatasource3().getPassword());
ds.setUrl(this.omsSegmentProperties.getDatasource3().getUrl());
ds.setInitSQL(SET_DEFAULT_SCHEMA);
return ds;
}
@Bean(name = "dataSource4")
@ConfigurationProperties(prefix = "oms.db.datasource4")
public DataSource dataSource4() {
String SET_DEFAULT_SCHEMA = "ALTER SESSION SET CURRENT_SCHEMA="
+ this.omsSegmentProperties.getDatasource4().getSchema().get(0);
DataSource ds = new DataSource();
ds.setDriverClassName(this.omsSegmentProperties.getDatasource4()
.getDriverClassName());
ds.setUsername(this.omsSegmentProperties.getDatasource4().getUsername());
ds.setPassword(this.omsSegmentProperties.getDatasource4().getPassword());
ds.setUrl(this.omsSegmentProperties.getDatasource4().getUrl());
ds.setInitSQL(SET_DEFAULT_SCHEMA);
return ds;
}
@Bean(name = "dataSource41")
@ConfigurationProperties(prefix = "oms.db.datasource4")
public DataSource dataSource41() {
String SET_DEFAULT_SCHEMA = "ALTER SESSION SET CURRENT_SCHEMA="
+ this.omsSegmentProperties.getDatasource4().getSchema().get(1);
DataSource ds = new DataSource();
ds.setDriverClassName(this.omsSegmentProperties.getDatasource4()
.getDriverClassName());
ds.setUsername(this.omsSegmentProperties.getDatasource4().getUsername());
ds.setPassword(this.omsSegmentProperties.getDatasource4().getPassword());
ds.setUrl(this.omsSegmentProperties.getDatasource4().getUrl());
ds.setInitSQL(SET_DEFAULT_SCHEMA);
return ds;
}
@Bean(name = "dataSource5")
@ConfigurationProperties(prefix = "oms.db.datasource5")
public DataSource dataSource5() {
String SET_DEFAULT_SCHEMA = "ALTER SESSION SET CURRENT_SCHEMA="
+ this.omsSegmentProperties.getDatasource5().getSchema().get(0);
DataSource ds = new DataSource();
ds.setDriverClassName(this.omsSegmentProperties.getDatasource5()
.getDriverClassName());
ds.setUsername(this.omsSegmentProperties.getDatasource5().getUsername());
ds.setPassword(this.omsSegmentProperties.getDatasource5().getPassword());
ds.setUrl(this.omsSegmentProperties.getDatasource5().getUrl());
ds.setInitSQL(SET_DEFAULT_SCHEMA);
return ds;
}
@Bean(name = "dataSource51")
@ConfigurationProperties(prefix = "oms.db.datasource5")
public DataSource dataSource51() {
String SET_DEFAULT_SCHEMA = "ALTER SESSION SET CURRENT_SCHEMA="
+ this.omsSegmentProperties.getDatasource5().getSchema().get(1);
DataSource ds = new DataSource();
ds.setDriverClassName(this.omsSegmentProperties.getDatasource5()
.getDriverClassName());
ds.setUsername(this.omsSegmentProperties.getDatasource5().getUsername());
ds.setPassword(this.omsSegmentProperties.getDatasource5().getPassword());
ds.setUrl(this.omsSegmentProperties.getDatasource5().getUrl());
ds.setInitSQL(SET_DEFAULT_SCHEMA);
return ds;
}
@Bean(name = "dataSource6")
@ConfigurationProperties(prefix = "oms.db.datasource6")
public DataSource dataSource6() {
String SET_DEFAULT_SCHEMA = "ALTER SESSION SET CURRENT_SCHEMA="
+ this.omsSegmentProperties.getDatasource6().getSchema().get(0);
DataSource ds = new DataSource();
ds.setDriverClassName(this.omsSegmentProperties.getDatasource6()
.getDriverClassName());
ds.setUsername(this.omsSegmentProperties.getDatasource6().getUsername());
ds.setPassword(this.omsSegmentProperties.getDatasource6().getPassword());
ds.setUrl(this.omsSegmentProperties.getDatasource6().getUrl());
ds.setInitSQL(SET_DEFAULT_SCHEMA);
return ds;
}
@Bean(name = "dataSource61")
@ConfigurationProperties(prefix = "oms.db.datasource6")
public DataSource dataSource61() {
String SET_DEFAULT_SCHEMA = "ALTER SESSION SET CURRENT_SCHEMA="
+ this.omsSegmentProperties.getDatasource6().getSchema().get(1);
DataSource ds = new DataSource();
ds.setDriverClassName(this.omsSegmentProperties.getDatasource6()
.getDriverClassName());
ds.setUsername(this.omsSegmentProperties.getDatasource6().getUsername());
ds.setPassword(this.omsSegmentProperties.getDatasource6().getPassword());
ds.setUrl(this.omsSegmentProperties.getDatasource6().getUrl());
ds.setInitSQL(SET_DEFAULT_SCHEMA);
return ds;
}
@Bean
public DynamicRoutingDataSourceResolver dataSource() {
DynamicRoutingDataSourceResolver resolver = new DynamicRoutingDataSourceResolver();
Map<Object, Object> dataSources = new HashMap<>();
dataSources.put(OMSSegmentEnum.KC1A, dataSource1());
dataSources.put(OMSSegmentEnum.KC2, dataSource11());
dataSources.put(OMSSegmentEnum.KC5, dataSource2());
dataSources.put(OMSSegmentEnum.KC6, dataSource21());
dataSources.put(OMSSegmentEnum.KM3, dataSource3());
dataSources.put(OMSSegmentEnum.KM4, dataSource31());
dataSources.put(OMSSegmentEnum.KM5, dataSource4());
dataSources.put(OMSSegmentEnum.KM6, dataSource41());
dataSources.put(OMSSegmentEnum.STL1A, dataSource5());
dataSources.put(OMSSegmentEnum.STL2, dataSource51());
dataSources.put(OMSSegmentEnum.STL3, dataSource6());
dataSources.put(OMSSegmentEnum.STL4, dataSource61());
resolver.setDefaultTargetDataSource(dataSource1());
resolver.setTargetDataSources(dataSources);
return resolver;
}
@Bean
public JdbcTemplate jdbcTemplate() {
return new JdbcTemplate(dataSource());
}
}
和调用类
@Repository
public class OMSGenericDAO {
private static final Logger log = Logger
.getLogger(OMSGenericDAO.class);
@Autowired
private JdbcTemplate jdbcTemplate;
public List<Object> fetch(String sql, Class clazz) {
List<Object> result = new ArrayList<>();
log.info("Executing the query : " + sql);
long start = System.currentTimeMillis();
result = jdbcTemplate.query(sql, new BeanPropertyRowMapper(clazz));
long end = System.currentTimeMillis();
log.info("List finished.Total no of records fetched ::" + result.size());
log.info("Time to fetch" + (end - start) / 1000 + "seconds");
return result;
}
public Object fetch(String sql, Class clazz, String... args) {
return jdbcTemplate.queryForObject(sql, args, clazz);
}
}
堆栈追踪:
: Got more than one input Future failure. Logging failures after the first
org.springframework.transaction.CannotCreateTransactionException: Could not open JDBC Connection for transaction; nested exception is org.apache.tomcat.jdbc.pool.PoolExhaustedException: [pool-177-thread-3] Timeout: Pool empty. Unable to fetch a connection in 30 seconds, none available[size:100; busy:100; idle:0; lastwait:30000].
at org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:289)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:373)
at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:447)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:277)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:656)
at com.att.first.oms.dataaccesslayer.service.OMSGenericQueryServiceImpl$$EnhancerBySpringCGLIB$$ae14cb26.fetch(<generated>)
at com.att.first.oms.dataaccesslayer.web.FirstJavaOMSDataAccessController.fetchFromSegment(FirstJavaOMSDataAccessController.java:64)
at com.att.first.oms.dataaccesslayer.web.FirstJavaOMSDataAccessController.access$000(FirstJavaOMSDataAccessController.java:28)
at com.att.first.oms.dataaccesslayer.web.FirstJavaOMSDataAccessController$1.call(FirstJavaOMSDataAccessController.java:81)
at com.att.first.oms.dataaccesslayer.web.FirstJavaOMSDataAccessController$1.call(FirstJavaOMSDataAccessController.java:79)
at com.google.common.util.concurrent.TrustedListenableFutureTask$TrustedFutureInterruptibleTask.runInterruptibly(TrustedListenableFutureTask.java:111)
at com.google.common.util.concurrent.InterruptibleTask.run(InterruptibleTask.java:58)
at com.google.common.util.concurrent.TrustedListenableFutureTask.run(TrustedListenableFutureTask.java:75)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.apache.tomcat.jdbc.pool.PoolExhaustedException: [pool-177-thread-3] Timeout: Pool empty. Unable to fetch a connection in 30 seconds, none available[size:100; busy:100; idle:0; lastwait:30000].
at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:703)
at org.apache.tomcat.jdbc.pool.ConnectionPool.getConnection(ConnectionPool.java:198)
at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:132)
at org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource.getConnection(AbstractRoutingDataSource.java:164)
at org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:246)
... 17 more