如何定位Druid连接池的连接泄漏问题?
1. Druid 中如何定位泄漏连接
在 Druid 连接池中,可以通过以下参数开启未归还连接的检测: removeAbandoned:是否回收超时未归还的连接,默认值为 false,表示不回收。 removeAbandonedTimeoutMillis:未归还连接的超时时间(单位:毫秒)。默认值为 300000(即 300 秒)。 logAbandoned:是否将超时未归还的连接信息打印到日志中。默认值为 false,表示不打印。
需要注意的是,logAbandoned 仅在 removeAbandoned 为 true 时生效。也就是说,Druid 连接池不支持仅打印,但不回收超时未归还连接的功能。
2. 实现细节
在DBCP 配置文件后面追加
removeAbandoned=true
logAbandoned=true
示例 在从连接池获取连接时,如果removeAbandoned为 true,则会记录连接的堆栈信息和创建时间,用于检测未归还连接。
########DBCP##########
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://192.168.xx.xx:3306/
initialSize=5
maxActive=250
keepAlive=true
minIdle=5
filters=stat
maxWait=6000
timeBetweenEvictionRunsMillis=60000
minEvictableIdleTimeMillis=300000
validationQuery=select 'x'
testOnBorrow=true
testOnReturn=false
testWhileIdle=true
poolPreparedStatements: true
maxOpenPreparedStatements: 20
removeAbandoned=true
logAbandoned=true
3.查看日志
在日志中搜索关键字 abandon connection , 可以定位到是代码 com.sie.iiot.apps.redis.utils.CommonUtils.getRbacTokenSuperuser(CommonUtils.java:33)
这里创建了数据库链接,但是是在线程中
com.sie.iiot.apps.taskscheduler.model.main.TaskScheduler
中执行的,因为线程一直在运行,导致链接不会释放
2025-07-21 14:10:41.694
2025-07-21 14:10:41.624 [Druid-ConnectionPool-Destroy-540642172] ERROR com.alibaba.druid.pool.DruidDataSource -abandon connection, owner thread: iiot_thread_general-0, connected at : 1753077917085, open stackTrace
2025-07-21 14:10:41.694
at java.lang.Thread.getStackTrace(Thread.java:1559)
2025-07-21 14:10:41.694
at com.alibaba.druid.pool.DruidDataSource.getConnectionDirect(DruidDataSource.java:1498)
2025-07-21 14:10:41.694
at com.alibaba.druid.filter.FilterChainImpl.dataSource_connect(FilterChainImpl.java:5059)
2025-07-21 14:10:41.694
at com.alibaba.druid.filter.stat.StatFilter.dataSource_getConnection(StatFilter.java:726)
2025-07-21 14:10:41.694
at com.alibaba.druid.filter.FilterChainImpl.dataSource_connect(FilterChainImpl.java:5055)
2025-07-21 14:10:41.694
at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:1407)
2025-07-21 14:10:41.694
at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:1399)
2025-07-21 14:10:41.694
at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:100)
2025-07-21 14:10:41.694
at com.sie.snest.engine.db.relationdb.RelationDBAccessor.<init>(RelationDBAccessor.java:216)
2025-07-21 14:10:41.694
at com.sie.snest.engine.a.a.getNewAccessorFromDataSource(AbstractDataSourceStrategy.java:123)
2025-07-21 14:10:41.695
at com.sie.snest.engine.a.a.getDbAccessor(AbstractDataSourceStrategy.java:106)
2025-07-21 14:10:41.695
at com.sie.snest.engine.a.h.getRelationDBAccessor(ModelMetaDataSourceStrategy.java:39)
2025-07-21 14:10:41.695
at com.sie.snest.engine.a.h.getRelationDBAccessor(ModelMetaDataSourceStrategy.java:32)
2025-07-21 14:10:41.695
at com.sie.snest.engine.data.access.BussModelDataAccess.getRelationDBAccessor(BussModelDataAccess.java:166)
2025-07-21 14:10:41.695
at com.sie.snest.engine.db.relationdb.FilterExpression.<init>(FilterExpression.java:439)
2025-07-21 14:10:41.695
at com.sie.snest.engine.data.access.BussModelDataAccess.a(BussModelDataAccess.java:2417)
2025-07-21 14:10:41.695
at com.sie.snest.engine.data.access.BussModelDataAccess.search(BussModelDataAccess.java:571)
2025-07-21 14:10:41.695
at sun.reflect.GeneratedMethodAccessor6.invoke(Unknown Source)
2025-07-21 14:10:41.695
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
2025-07-21 14:10:41.695
at java.lang.reflect.Method.invoke(Method.java:498)
2025-07-21 14:10:41.695
at com.sie.snest.engine.model.MethodMeta.execute(MethodMeta.java:274)
2025-07-21 14:10:41.695
at com.sie.snest.engine.model.MethodMeta.invoke(MethodMeta.java:197)
2025-07-21 14:10:41.695
at com.sie.snest.engine.api.distributed.RpcInvocationV2.invoke(RpcInvocationV2.java:168)
2025-07-21 14:10:41.695
at com.sie.snest.engine.data.RecordSet.call(RecordSet.java:361)
2025-07-21 14:10:41.695
at com.sie.snest.engine.data.RecordSet.search(RecordSet.java:185)
2025-07-21 14:10:41.695
at com.sie.iiot.apps.redis.utils.CommonUtils.getRbacTokenSuperuser(CommonUtils.java:33)
2025-07-21 14:10:41.695
at com.sie.iiot.apps.redis.utils.CommonUtils.setToken(CommonUtils.java:29)
2025-07-21 14:10:41.695
at com.sie.iiot.apps.redis.model.RedisUtils.<init>(RedisUtils.java:61)
2025-07-21 14:10:41.695
at com.sie.iiot.apps.redis.model.RedisUtils$$EnhancerByCGLIB$$6461d573.<init>(<generated>)
2025-07-21 14:10:41.695
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
2025-07-21 14:10:41.695
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
2025-07-21 14:10:41.695
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
2025-07-21 14:10:41.695
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
2025-07-21 14:10:41.695
at net.sf.cglib.core.ReflectUtils.newInstance(ReflectUtils.java:291)
2025-07-21 14:10:41.695
at net.sf.cglib.proxy.Enhancer$EnhancerFactoryData.newInstance(Enhancer.java:448)
2025-07-21 14:10:41.695
at net.sf.cglib.proxy.Enhancer.nextInstance(Enhancer.java:700)
2025-07-21 14:10:41.695
at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:298)
2025-07-21 14:10:41.695
at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:480)
2025-07-21 14:10:41.695
at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:305)
2025-07-21 14:10:41.695
at com.sie.snest.engine.model.MethodMeta.getInstance(MethodMeta.java:402)
2025-07-21 14:10:41.695
at com.sie.snest.engine.model.MethodMeta.invoke(MethodMeta.java:202)
2025-07-21 14:10:41.695
at com.sie.snest.engine.api.distributed.RpcInvocationV2.invoke(RpcInvocationV2.java:168)
2025-07-21 14:10:41.695
at com.sie.snest.engine.data.RecordSet.call(RecordSet.java:361)
2025-07-21 14:10:41.695
at com.sie.iiot.apps.base.model.deployment.BaseDeployment.init(BaseDeployment.java:29)
2025-07-21 14:10:41.695
at com.sie.iiot.apps.base.model.deployment.BaseDeployment$$EnhancerByCGLIB$$7b8e4b18.CGLIB$init$5(<generated>)
2025-07-21 14:10:41.695
at com.sie.iiot.apps.base.model.deployment.BaseDeployment$$EnhancerByCGLIB$$7b8e4b18$$FastClassByCGLIB$$fb1ca8f7.invoke(<generated>)
2025-07-21 14:10:41.695
at net.sf.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
2025-07-21 14:10:41.695
at com.sie.snest.engine.model.ModelInterceptor.intercept(ModelInterceptor.java:84)
2025-07-21 14:10:41.695
at com.sie.iiot.apps.base.model.deployment.BaseDeployment$$EnhancerByCGLIB$$7b8e4b18.init(<generated>)
2025-07-21 14:10:41.695
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
2025-07-21 14:10:41.695
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
2025-07-21 14:10:41.695
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
2025-07-21 14:10:41.695
at java.lang.reflect.Method.invoke(Method.java:498)
2025-07-21 14:10:41.695
at com.sie.snest.engine.model.MethodMeta.execute(MethodMeta.java:274)
2025-07-21 14:10:41.695
at com.sie.snest.engine.model.MethodMeta.invoke(MethodMeta.java:204)
2025-07-21 14:10:41.695
at com.sie.snest.engine.api.distributed.RpcInvocationV2.invoke(RpcInvocationV2.java:168)
2025-07-21 14:10:41.695
at com.sie.snest.engine.data.RecordSet.call(RecordSet.java:361)
2025-07-21 14:10:41.695
at com.sie.iiot.apps.taskscheduler.model.main.TaskScheduler.executeRealTimeTask(TaskScheduler.java:775)
2025-07-21 14:10:41.695
at com.sie.iiot.apps.taskscheduler.model.main.TaskScheduler.lambda$realTimeTaskBase$0(TaskScheduler.java:95)
2025-07-21 14:10:41.695
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
2025-07-21 14:10:41.695
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
2025-07-21 14:10:41.695
at java.lang.Thread.run(Thread.java:748)
2025-07-21 14:10:41.695
ownerThread current state is RUNNABLE, current stackTrace
2025-07-21 14:10:41.695
at java.net.SocketInputStream.socketRead0(Native Method)
2025-07-21 14:10:41.695
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
2025-07-21 14:10:41.695
at java.net.SocketInputStream.read(SocketInputStream.java:171)
2025-07-21 14:10:41.695
at java.net.SocketInputStream.read(SocketInputStream.java:141)
2025-07-21 14:10:41.695
at java.net.SocketInputStream.read(SocketInputStream.java:127)
2025-07-21 14:10:41.695
at redis.clients.jedis.util.RedisInputStream.ensureFill(RedisInputStream.java:202)
2025-07-21 14:10:41.695
at redis.clients.jedis.util.RedisInputStream.readByte(RedisInputStream.java:46)
2025-07-21 14:10:41.695
at redis.clients.jedis.Protocol.process(Protocol.java:126)
2025-07-21 14:10:41.695
at redis.clients.jedis.Protocol.read(Protocol.java:192)
2025-07-21 14:10:41.695
at redis.clients.jedis.Connection.readProtocolWithCheckingBroken(Connection.java:316)
2025-07-21 14:10:41.695
at redis.clients.jedis.Connection.getUnflushedObjectMultiBulkReply(Connection.java:282)
2025-07-21 14:10:41.695
at redis.clients.jedis.JedisPubSub.process(JedisPubSub.java:135)
2025-07-21 14:10:41.696
at redis.clients.jedis.JedisPubSub.proceed(JedisPubSub.java:125)
2025-07-21 14:10:41.696
at redis.clients.jedis.Jedis.subscribe(Jedis.java:7908)
2025-07-21 14:10:41.696
at com.sie.iiot.apps.redis.model.RedisUtils.subscribe(RedisUtils.java:2397)
2025-07-21 14:10:41.696
at com.sie.iiot.apps.redis.model.RedisUtils$$EnhancerByCGLIB$$6461d573.CGLIB$subscribe$72(<generated>)
2025-07-21 14:10:41.696
at com.sie.iiot.apps.redis.model.RedisUtils$$EnhancerByCGLIB$$6461d573$$FastClassByCGLIB$$4ad4bcdf.invoke(<generated>)
2025-07-21 14:10:41.696
at net.sf.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
2025-07-21 14:10:41.696
at com.sie.snest.engine.model.ModelInterceptor.intercept(ModelInterceptor.java:84)
2025-07-21 14:10:41.696
at com.sie.iiot.apps.redis.model.RedisUtils$$EnhancerByCGLIB$$6461d573.subscribe(<generated>)
2025-07-21 14:10:41.696
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
2025-07-21 14:10:41.696
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
2025-07-21 14:10:41.696
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
2025-07-21 14:10:41.696
at java.lang.reflect.Method.invoke(Method.java:498)
2025-07-21 14:10:41.696
at com.sie.snest.engine.model.MethodMeta.execute(MethodMeta.java:274)
2025-07-21 14:10:41.696
at com.sie.snest.engine.model.MethodMeta.invoke(MethodMeta.java:204)
2025-07-21 14:10:41.696
at com.sie.snest.engine.api.distributed.RpcInvocationV2.invoke(RpcInvocationV2.java:168)
2025-07-21 14:10:41.696
at com.sie.snest.engine.data.RecordSet.call(RecordSet.java:361)
2025-07-21 14:10:41.696
at com.sie.iiot.apps.base.model.deployment.BaseDeployment.init(BaseDeployment.java:29)
2025-07-21 14:10:41.696
at com.sie.iiot.apps.base.model.deployment.BaseDeployment$$EnhancerByCGLIB$$7b8e4b18.CGLIB$init$5(<generated>)
2025-07-21 14:10:41.696
at com.sie.iiot.apps.base.model.deployment.BaseDeployment$$EnhancerByCGLIB$$7b8e4b18$$FastClassByCGLIB$$fb1ca8f7.invoke(<generated>)
2025-07-21 14:10:41.696
at net.sf.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
2025-07-21 14:10:41.696
at com.sie.snest.engine.model.ModelInterceptor.intercept(ModelInterceptor.java:84)
2025-07-21 14:10:41.696
at com.sie.iiot.apps.base.model.deployment.BaseDeployment$$EnhancerByCGLIB$$7b8e4b18.init(<generated>)
2025-07-21 14:10:41.696
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
2025-07-21 14:10:41.696
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
2025-07-21 14:10:41.696
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
4. 解决方式
如果是在线程中执行了SQL操作,那么需要业务代码自己手动的去创建meta和显示的调用 meta.close()
请参考: 03.meta上下文使用规范