使用 Spring 的 Tomcat 数据源池中的所有连接都处于活动状态
Posted
技术标签:
【中文标题】使用 Spring 的 Tomcat 数据源池中的所有连接都处于活动状态【英文标题】:All connections are active in Tomcat datasource pool with Spring 【发布时间】:2018-05-19 12:20:22 【问题描述】:我的 Spring Boot 应用程序使用 JDBCTemplate 将 SQL 查询发送到 PostgreSQL 数据库。似乎每次模板从池中获取连接时,连接都不会被释放。活动连接数 (datasource.primary.active) 一直在增加。
在日志中,使用 JDBCTemplate 进行 SQL 查询后,我可以看到:
DEBUG o.s.j.d.DataSourceUtils - Returning JDBC Connection to DataSource
但是空闲连接数保持不变,活动连接数没有减少。当达到最大值时,将无法检索连接以执行查询。
所以,我认为没有返回到数据源池的连接,请知道吗?
这是使用 Actuator 获得的数据源配置:
"dataSource":
"prefix": "spring.datasource.tomcat",
"properties":
"connectionProperties": null,
"propagateInterruptState": false,
"validator": null,
"useDisposableConnectionFacade": true,
"defaultCatalog": null,
"validationInterval": 3000,
"jmxEnabled": true,
"ignoreExceptionOnPreLoad": false,
"logAbandoned": false,
"commitOnReturn": false,
"password": "******",
"maxIdle": 100,
"testWhileIdle": false,
"removeAbandoned": false,
"poolProperties":
"dbProperties":
"user": "postgres",
"password": "******"
,
"url": "jdbc:postgresql://localhost:5432/tvir",
"driverClassName": "org.postgresql.Driver",
"defaultAutoCommit": null,
"defaultReadOnly": null,
"defaultTransactionIsolation": -1,
"defaultCatalog": null,
"connectionProperties": null,
"initialSize": 10,
"maxActive": 100,
"maxIdle": 100,
"minIdle": 10,
"maxWait": 30000,
"validationQuery": "SELECT 1",
"validationQueryTimeout": -1,
"validatorClassName": null,
"validator": null,
"testOnBorrow": true,
"testOnReturn": false,
"testWhileIdle": false,
"timeBetweenEvictionRunsMillis": 5000,
"numTestsPerEvictionRun": 0,
"minEvictableIdleTimeMillis": 60000,
"accessToUnderlyingConnectionAllowed": true,
"removeAbandoned": false,
"removeAbandonedTimeout": 60,
"logAbandoned": false,
"name": "Tomcat Connection Pool[1-574817798]",
"password": "******",
"username": "postgres",
"validationInterval": 3000,
"jmxEnabled": true,
"initSQL": null,
"testOnConnect": false,
"jdbcInterceptors": null,
"fairQueue": true,
"useEquals": true,
"abandonWhenPercentageFull": 0,
"maxAge": 0,
"useLock": false,
"suspectTimeout": 0,
"dataSource": null,
"dataSourceJNDI": null,
"alternateUsernameAllowed": false,
"commitOnReturn": false,
"rollbackOnReturn": false,
"useDisposableConnectionFacade": true,
"logValidationErrors": false,
"propagateInterruptState": false,
"ignoreExceptionOnPreLoad": false,
"useStatementFacade": true
,
以及用于查询数据库的代码:
JdbcTemplate jdbcTemplate = appCtx.getBean(JdbcTemplate.class);
ResultSet columns = jdbcTemplate.getDataSource().getConnection().getMetaData().getColumns(null, null, source.getTable().toLowerCase(), null);
String selectList = "";
while (columns.next())
String colName = columns.getString("COLUMN_NAME");
String colType = columns.getString("DATA_TYPE");
if(!selectList.equals(""))
selectList += ", ";
if((""+java.sql.Types.INTEGER).equalsIgnoreCase(colType) ||
(""+java.sql.Types.DOUBLE).equalsIgnoreCase(colType) ||
(""+java.sql.Types.BIGINT).equalsIgnoreCase(colType) ||
(""+java.sql.Types.FLOAT).equalsIgnoreCase(colType) )
selectList += "SUM(" + colName + ")";
else
selectList += "MAX(" + colName + ")";
selectList += " AS "+colName;
String sql = "SELECT "+selectList+" FROM "+source.getTable()+" "+
"WHERE "+source.getDateColumn()+" >= ? "+
"AND "+source.getDateColumn()+" <= ? ";
List<Map<String, Object>> results = jdbcTemplate.queryForList(sql, Date.valueOf(startDate), Date.valueOf(endDate));
【问题讨论】:
这通常意味着您要么有错误的事务设置,要么在 spring 范围之外自己弄乱了连接。 我使用的是默认事务模式,这是来自数据源的参数:"defaultTransactionIsolation": -1
并且请求是通过jdbcTemplate.queryForList()
完成的
那么你自己在 Spring 范围之外搞乱了连接。为您的问题添加一些代码和配置。
我已经添加了 conf 和 code。可能它与元数据部分相关联?我可以使用这种方式获得连接吗?如何在没有连接的情况下获取元数据?
不,你不能也不应该因为这是连接泄漏(改用ConnectionCallback
),还有一点可疑(至少在我的书中)是你这样做appCtx.getBean(JdbcTemplate.class)
你应该使用依赖注入而不是自己从上下文中获取bean。
【参考方案1】:
Spring boot 允许您配置您希望数据源的行为方式。 您可以在official doc 上找到完整列表。 检查您的案例的以下属性:
spring.datasource.maxActive
spring.datasource.maxIdle
根据您使用的连接池,您还可以使用 Spring Boot 属性对其进行调整(一切都在文档中)。
【讨论】:
我使用默认值,所以maxActive=100
和 maxIdle=10
。此配置中的任何内容都可以解释为什么连接没有回到空闲模式?以上是关于使用 Spring 的 Tomcat 数据源池中的所有连接都处于活动状态的主要内容,如果未能解决你的问题,请参考以下文章
Spring Boot 应用程序的 tomcat 中的默认线程池
Spring Cloud Gateway中netty线程池优化
org.apache.tomcat.util.bcel.classfile.ClassFormatException:常量池中的无效字节标记:15