数据库连接泄漏是可以隐藏的东西,除非特别注意,否则将在系统高峰期最关键的阶段暴露出来。 我们将手动检查所有打开的连接是否已正确关闭。 然后,我们将提供各种代码质量插件来进行扫描和检查。 当连接通过复杂的程序结构传递时,这两个都可能会丢失可能的连接泄漏。 然后在单元测试或集成测试级别,我们可以进行检查以验证连接池中的计数,以避免这种不幸的情况,这种情况会使工程师在年末或黑色星期五忙,等等:)
在不幸的情况下,由于性能下降或整个系统崩溃(可通过JDBC连接泄漏传播),当我们怀疑连接泄漏时,如何轻松而Swift地找出罪魁祸首。 在Tomcat连接池中,我们可以使用3个属性来完成此操作。
removeAbandoned
如果数据库连接已被放弃(一段时间未使用,但尚未返回到池中),则此配置将尝试删除它。 以下配置配置了删除连接之前要等待的时间。
removeAbandonedTimeout
在尝试删除连接之前,它将花费的时间。 默认情况下为60s。
注意:当我们将此属性与目标一起使用来隔离罪魁祸首时,了解系统将在数据库上执行的最长事务所花费的平均时间很有用。 将此值设置为比该值大得多的值将避免我们捕获可能实际上在做有用工作的无辜线程,最后将被适当地关闭。
logAbandoned
以此来控制“删除删除的连接时是否应记录堆栈跟踪”。
有关这些属性的更多详细信息,请参见
https://tomcat.apache.org/tomcat-8.0-doc/jdbc-pool.html#Common_Attributes
如果您怀疑应用程序是否有泄漏,这些配置也可以用作安全网。 因为它将自动删除已忘记关闭的连接,并且池将进行处理以适当考虑这些,从而保持预期的最小,最大和空闲连接数。
这是我在池中删除废弃连接时捕获的示例日志。
[ 2020 - 04 - 24 00 : 26 : 13 , 229 ] WARN {org.apache.tomcat.jdbc.pool.ConnectionPool} - Connection has been abandoned PooledConnection[com.mysql.jdbc.JDBC4Connection @5ab91385 ]:java.lang.Exception at org.apache.tomcat.jdbc.pool.ConnectionPool.getThreadDump(ConnectionPool.java: 1096 ) at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java: 799 ) at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java: 648 ) at org.apache.tomcat.jdbc.pool.ConnectionPool.getConnection(ConnectionPool.java: 200 ) at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java: 128 ) at org.lanka.carbon.user.core.jdbc.JDBCUserStoreManager.getDBConnection(JDBCUserStoreManager.java: 1187 ) at org.lanka.sample.CustomUserStoreManager.doAuthenticate(CustomUserStoreManager.java: 51 ) at org.lanka.carbon.user.core.common.AbstractUserStoreManager.authenticateInternal(AbstractUserStoreManager.java: 674 ) at org.lanka.carbon.user.core.common.AbstractUserStoreManager.access$ 100 (AbstractUserStoreManager.java: 86 ) at org.lanka.carbon.user.core.common.AbstractUserStoreManager$ 4 .run(AbstractUserStoreManager.java: 542 ) at org.lanka.carbon.user.core.common.AbstractUserStoreManager$ 4 .run(AbstractUserStoreManager.java: 539 ) at java.security.AccessController.doPrivileged(Native Method) at org.lanka.carbon.user.core.common.AbstractUserStoreManager.authenticate(AbstractUserStoreManager.java: 539 ) at org.lanka.carbon.user.core.common.AbstractUserStoreManager.authenticateInternal(AbstractUserStoreManager.java: 702 ) at org.lanka.carbon.user.core.common.AbstractUserStoreManager.access$ 100 (AbstractUserStoreManager.java: 86 ) at org.lanka.carbon.user.core.common.AbstractUserStoreManager$ 4 .run(AbstractUserStoreManager.java: 542 ) at org.lanka.carbon.user.core.common.AbstractUserStoreManager$ 4 .run(AbstractUserStoreManager.java: 539 ) at java.security.AccessController.doPrivileged(Native Method) at org.lanka.carbon.user.core.common.AbstractUserStoreManager.authenticate(AbstractUserStoreManager.java: 539 ) at org.lanka.carbon.user.core.common.AbstractUserStoreManager$ 3 .run(AbstractUserStoreManager.java: 522 ) at org.lanka.carbon.user.core.common.AbstractUserStoreManager$ 3 .run(AbstractUserStoreManager.java: 514 ) at java.security.AccessController.doPrivileged(Native Method)
您可以在此处捕获与废弃连接创建相关的整个堆栈跟踪,这将使我们更快地找到问题的根源。
(可选)我们还可以选择使用JConsole通过JMX监视JDBC池。 为此,我们需要启用属性“ jmxEnabled'
,该属性将允许从Jconsole连接到JDBC池。 完成后,它具有监视池的许多功能,甚至可以设置为在检测到连接被放弃时发出通知。
希望这可以帮助您节省一些时间进行故障排除。
干杯!
翻译自: https://www.javacodegeeks.com/2020/04/tomcat-jdbc-pool-connection-leak-catch-the-culprit.html