23

我已经浏览了一段时间,并在此过程中咬牙切齿,但找不到与我的问题完全匹配的问题。
简而言之,在 60 秒不活动后,我得到了极好的堆栈跟踪(org.apache.tomcat.jdbc.pool.ConnectionPool 放弃),这是几个服务器端线程的正常行为。
我正在使用 Tomcat JDBC 连接池(org.apache.tomcat.jdbc.pool.DataSource)直接
堆栈跟踪:

    2012 年 10 月 29 日 8:55:50 PM org.apache.tomcat.jdbc.pool.ConnectionPool 放弃
    警告:连接已被放弃 PooledConnection[com.mysql.jdbc.JDBC4Connection@1ad2916]:java.lang.Exception
        在 org.apache.tomcat.jdbc.pool.ConnectionPool.getThreadDump(ConnectionPool.java:967)
        在 org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:721)
        在 org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:579)
        在 org.apache.tomcat.jdbc.pool.ConnectionPool.getConnection(ConnectionPool.java:174)
        在 org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:111)
        在 com.getsom.getConnection(DAO.java:1444)
        在 com.getsom.PreparedConnection.(PreparedConnection.java:48)
        在 com.getsom.Alarms.run(Alarms.java:492)

我的 PoolProperties 配置如下:

    PoolProperties pp = new PoolProperties();

    pp.setUrl( someValidUrl);
    pp.setDriverClassName("com.mysql.jdbc.Driver");
    pp.setUsername( someUser);
    pp.setPassword( somePassword);
    pp.setJmxEnabled( true);
    pp.setTestWhileIdle( true);
    pp.setTestOnBorrow( true);
    pp.setValidationQuery( "SELECT 1");
    pp.setTestOnReturn( false);
    pp.setValidationInterval(30000);
    pp.setTimeBetweenEvictionRunsMillis(30000);
    pp.setMaxActive(100);
    pp.setInitialSize(10);
    pp.setMaxWait(10000);
    pp.setMinEvictableIdleTimeMillis(30000);
    pp.setMinIdle(10);

    pp.setLogAbandoned(true);
    pp.setRemoveAbandoned(true);
    pp.setRemoveAbandonedTimeout(60);
    pp.setJdbcInterceptors("org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;"+
      "org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer");    

    setPoolProperties(pp);

我希望 setValidationInterval(30000) 能救我,因为 30 秒在连接生命周期中并不多。无论如何,问题是:
我缺少什么来保持这种联系永远存在?
很高兴知道:为什么我在声明连接的函数中超时,尽管它在 30 秒前被调用。

4

8 回答 8

49

即使我迟到了 1 年多才访问此页面,但我偶然发现了这里,因为我遇到了类似的问题并且也需要解决方案。所以我想我会分享最终对我有用的东西。

就我而言,在找到并阅读了这篇文章后 >>>配置-jdbc-pool-high-concurrency - 我只是在我的池配置中添加了一个这样的拦截器;

"org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer"

这样您所做的行(来自您上面发布的代码)setJdbcInterceptors(...)现在应该如下所示;

p.setJdbcInterceptors(
            "org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;"
            + "org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer;"
            + "org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer");

解释- 从文章中引用,它说;

我们要确保当我们检测到连接仍在使用时,我们重置超时计时器,这样连接就不会被视为放弃。我们通过插入一个拦截器来做到这一点。

每次准备语句或执行查询时,计时器都会重置连接池上的放弃计时器。这样......做大量的查询和更新,不会超时。

记住你很可能很久以前就已经解决了这个问题,我仍然希望这可以帮助其他遇到类似问题的人,就像我一样。

干杯!

于 2013-12-15T22:15:49.087 回答
4

您是否看过 Tomcat 网站上与PoolConnection相关的信息。也许您需要的是查看属性minEvictableIdleTimeMillis

要回答您的问题,您将超时,因为您每 30 秒检查一次空闲和放弃连接(请参阅TimeBetweenEvictionRunsMillis参考资料),并且由于您在 30 秒设置了可撤销的空闲超时时间(请参阅参考资料minEvictableIdleTimeMillis),因此您最终得到了您所拥有的。您说过您在空闲时收到此异常,我怀疑该异常是关闭空闲连接而不是放弃连接的结果。据我了解,放弃连接用于超时时间超过预期的查询(而不是空闲连接)。

就我个人而言,我不希望连接永远存在,因为它们会不必要地消耗资源(即与数据库的连接)。我会玩弄我的最大连接数、驱逐运行和空闲时间来优化我自己的需求。我想你可以将这些值设置得足够大,几乎永远存在!这确实取决于你在做什么......

抱歉,我不能在这里提供更多帮助。

于 2012-10-30T07:27:04.437 回答
4

只需在 tomcat7 conf/server.xml 或 context.xml 中添加以下条目即可,只要您的资源标签存在即可。

jdbcInterceptors="org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;
org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer;
org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer"
于 2016-08-01T15:38:18.550 回答
1

在配置文件中跟踪“removeAbandonedTimeout”。这应该是应用程序中的最大运行查询。否则它将在执行过程中关闭连接

于 2014-10-08T08:35:48.577 回答
1

如果您在 tomcat 的 context.xml 中定义数据源,则应添加 ResetAbandonedTimer,如下所示:

jdbcInterceptors="ConnectionState;StatementFinalizer;ResetAbandonedTimer"

设置 ResetAbandonedTimer 后,问题在我的应用程序中得到解决,请求您让我知道 ResetAbandonedTimer 拦截器和 removeAbandoned="true" removeAbandonedTimeout="60" 之间是否有任何关系

于 2017-10-20T04:40:19.787 回答
0

有一个类似的问题,即 tomcat 正在关闭 JDBC 连接,因为它被放弃了,因为事务需要很长时间。

通过意识到abandonedandidle是不同的并通过设置来解决它:spring.datasource.tomcat.removeAbandonedTimeout: 86400 #seconds

于 2019-03-02T11:58:40.753 回答
0

这个问题的答案对我很有帮助。

虽然就我而言,我已经配置了“ResetAbandonedTimer”JDBC 拦截器。

但是,我的查询运行时间比我还配置的“removeAbandonedTimeout”更长。一旦我增加了“removeAbandonedTimeout”,问题就消失了。

于 2018-02-16T21:03:05.960 回答
0

我可以看到这个线程很旧,但我遇到了类似的问题,我最终找到了导致它的原因,所以如果它可以帮助某人,我想分享一下:

我使用了来自一个安静的网络服务的连接。在服务器端处理来自客户端的请求的界面中,我不小心在方法签名中放入了“抛出 IOException”:

@GET
@Path("/databases")
@Produces(MediaType.APPLICATION_JSON)
public String getAllDatabases() throws IOException {
于 2019-09-10T09:03:50.157 回答