\345\246\202\344\275\225\345\256\232\344\275\215Druid\350\277\236\346\216\245\346\261\240\347\232\204\350\277\236\346\216\245\346\263\204\346\274\217\351\227\256\351\242\230\357\274\237.md
... ...
@@ -0,0 +1,261 @@
1
+# 如何定位 Druid & HikariCP 连接池的连接泄漏问题?
2
+
3
+## 1. Druid 中如何定位泄漏连接
4
+
5
+在 Druid 连接池中,可以通过以下参数开启未归还连接的检测:
6
+removeAbandoned:是否回收超时未归还的连接,默认值为 false,表示不回收。
7
+removeAbandonedTimeoutMillis:未归还连接的超时时间(单位:毫秒)。默认值为 300000(即 300 秒)。
8
+logAbandoned:是否将超时未归还的连接信息打印到日志中。默认值为 false,表示不打印。
9
+
10
+需要注意的是,logAbandoned 仅在 removeAbandoned 为 true 时生效。也就是说,Druid 连接池不支持仅打印,但不回收超时未归还连接的功能。
11
+
12
+## 2. 实现细节
13
+在DBCP 配置文件后面追加
14
+```
15
+removeAbandoned=true
16
+logAbandoned=true
17
+```
18
+
19
+示例
20
+在从连接池获取连接时,如果removeAbandoned为 true,则会记录连接的堆栈信息和创建时间,用于检测未归还连接。
21
+
22
+```xml
23
+########DBCP##########
24
+driverClassName=com.mysql.cj.jdbc.Driver
25
+url=jdbc:mysql://192.168.xx.xx:3306/
26
+initialSize=5
27
+maxActive=250
28
+keepAlive=true
29
+minIdle=5
30
+filters=stat
31
+maxWait=6000
32
+timeBetweenEvictionRunsMillis=60000
33
+minEvictableIdleTimeMillis=300000
34
+validationQuery=select 'x'
35
+testOnBorrow=true
36
+testOnReturn=false
37
+testWhileIdle=true
38
+poolPreparedStatements: true
39
+maxOpenPreparedStatements: 20
40
+removeAbandoned=true
41
+logAbandoned=true
42
+```
43
+
44
+## 3.查看日志
45
+在日志中搜索关键字 abandon connection , 可以定位到是代码 `com.sie.iiot.apps.redis.utils.CommonUtils.getRbacTokenSuperuser(CommonUtils.java:33)` 这里创建了数据库链接,但是是在线程中
46
+`com.sie.iiot.apps.taskscheduler.model.main.TaskScheduler`中执行的,因为线程一直在运行,导致链接不会释放
47
+
48
+```
49
+2025-07-21 14:10:41.694
50
+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
51
+2025-07-21 14:10:41.694
52
+ at java.lang.Thread.getStackTrace(Thread.java:1559)
53
+2025-07-21 14:10:41.694
54
+ at com.alibaba.druid.pool.DruidDataSource.getConnectionDirect(DruidDataSource.java:1498)
55
+2025-07-21 14:10:41.694
56
+ at com.alibaba.druid.filter.FilterChainImpl.dataSource_connect(FilterChainImpl.java:5059)
57
+2025-07-21 14:10:41.694
58
+ at com.alibaba.druid.filter.stat.StatFilter.dataSource_getConnection(StatFilter.java:726)
59
+2025-07-21 14:10:41.694
60
+ at com.alibaba.druid.filter.FilterChainImpl.dataSource_connect(FilterChainImpl.java:5055)
61
+2025-07-21 14:10:41.694
62
+ at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:1407)
63
+2025-07-21 14:10:41.694
64
+ at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:1399)
65
+2025-07-21 14:10:41.694
66
+ at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:100)
67
+2025-07-21 14:10:41.694
68
+ at com.sie.snest.engine.db.relationdb.RelationDBAccessor.<init>(RelationDBAccessor.java:216)
69
+2025-07-21 14:10:41.694
70
+ at com.sie.snest.engine.a.a.getNewAccessorFromDataSource(AbstractDataSourceStrategy.java:123)
71
+2025-07-21 14:10:41.695
72
+ at com.sie.snest.engine.a.a.getDbAccessor(AbstractDataSourceStrategy.java:106)
73
+2025-07-21 14:10:41.695
74
+ at com.sie.snest.engine.a.h.getRelationDBAccessor(ModelMetaDataSourceStrategy.java:39)
75
+2025-07-21 14:10:41.695
76
+ at com.sie.snest.engine.a.h.getRelationDBAccessor(ModelMetaDataSourceStrategy.java:32)
77
+2025-07-21 14:10:41.695
78
+ at com.sie.snest.engine.data.access.BussModelDataAccess.getRelationDBAccessor(BussModelDataAccess.java:166)
79
+2025-07-21 14:10:41.695
80
+ at com.sie.snest.engine.db.relationdb.FilterExpression.<init>(FilterExpression.java:439)
81
+2025-07-21 14:10:41.695
82
+ at com.sie.snest.engine.data.access.BussModelDataAccess.a(BussModelDataAccess.java:2417)
83
+2025-07-21 14:10:41.695
84
+ at com.sie.snest.engine.data.access.BussModelDataAccess.search(BussModelDataAccess.java:571)
85
+2025-07-21 14:10:41.695
86
+ at sun.reflect.GeneratedMethodAccessor6.invoke(Unknown Source)
87
+2025-07-21 14:10:41.695
88
+ at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
89
+2025-07-21 14:10:41.695
90
+ at java.lang.reflect.Method.invoke(Method.java:498)
91
+2025-07-21 14:10:41.695
92
+ at com.sie.snest.engine.model.MethodMeta.execute(MethodMeta.java:274)
93
+2025-07-21 14:10:41.695
94
+ at com.sie.snest.engine.model.MethodMeta.invoke(MethodMeta.java:197)
95
+2025-07-21 14:10:41.695
96
+ at com.sie.snest.engine.api.distributed.RpcInvocationV2.invoke(RpcInvocationV2.java:168)
97
+2025-07-21 14:10:41.695
98
+ at com.sie.snest.engine.data.RecordSet.call(RecordSet.java:361)
99
+2025-07-21 14:10:41.695
100
+ at com.sie.snest.engine.data.RecordSet.search(RecordSet.java:185)
101
+2025-07-21 14:10:41.695
102
+ at com.sie.iiot.apps.redis.utils.CommonUtils.getRbacTokenSuperuser(CommonUtils.java:33)
103
+2025-07-21 14:10:41.695
104
+ at com.sie.iiot.apps.redis.utils.CommonUtils.setToken(CommonUtils.java:29)
105
+2025-07-21 14:10:41.695
106
+ at com.sie.iiot.apps.redis.model.RedisUtils.<init>(RedisUtils.java:61)
107
+2025-07-21 14:10:41.695
108
+ at com.sie.iiot.apps.redis.model.RedisUtils$$EnhancerByCGLIB$$6461d573.<init>(<generated>)
109
+2025-07-21 14:10:41.695
110
+ at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
111
+2025-07-21 14:10:41.695
112
+ at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
113
+2025-07-21 14:10:41.695
114
+ at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
115
+2025-07-21 14:10:41.695
116
+ at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
117
+2025-07-21 14:10:41.695
118
+ at net.sf.cglib.core.ReflectUtils.newInstance(ReflectUtils.java:291)
119
+2025-07-21 14:10:41.695
120
+ at net.sf.cglib.proxy.Enhancer$EnhancerFactoryData.newInstance(Enhancer.java:448)
121
+2025-07-21 14:10:41.695
122
+ at net.sf.cglib.proxy.Enhancer.nextInstance(Enhancer.java:700)
123
+2025-07-21 14:10:41.695
124
+ at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:298)
125
+2025-07-21 14:10:41.695
126
+ at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:480)
127
+2025-07-21 14:10:41.695
128
+ at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:305)
129
+2025-07-21 14:10:41.695
130
+ at com.sie.snest.engine.model.MethodMeta.getInstance(MethodMeta.java:402)
131
+2025-07-21 14:10:41.695
132
+ at com.sie.snest.engine.model.MethodMeta.invoke(MethodMeta.java:202)
133
+2025-07-21 14:10:41.695
134
+ at com.sie.snest.engine.api.distributed.RpcInvocationV2.invoke(RpcInvocationV2.java:168)
135
+2025-07-21 14:10:41.695
136
+ at com.sie.snest.engine.data.RecordSet.call(RecordSet.java:361)
137
+2025-07-21 14:10:41.695
138
+ at com.sie.iiot.apps.base.model.deployment.BaseDeployment.init(BaseDeployment.java:29)
139
+2025-07-21 14:10:41.695
140
+ at com.sie.iiot.apps.base.model.deployment.BaseDeployment$$EnhancerByCGLIB$$7b8e4b18.CGLIB$init$5(<generated>)
141
+2025-07-21 14:10:41.695
142
+ at com.sie.iiot.apps.base.model.deployment.BaseDeployment$$EnhancerByCGLIB$$7b8e4b18$$FastClassByCGLIB$$fb1ca8f7.invoke(<generated>)
143
+2025-07-21 14:10:41.695
144
+ at net.sf.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
145
+2025-07-21 14:10:41.695
146
+ at com.sie.snest.engine.model.ModelInterceptor.intercept(ModelInterceptor.java:84)
147
+2025-07-21 14:10:41.695
148
+ at com.sie.iiot.apps.base.model.deployment.BaseDeployment$$EnhancerByCGLIB$$7b8e4b18.init(<generated>)
149
+2025-07-21 14:10:41.695
150
+ at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
151
+2025-07-21 14:10:41.695
152
+ at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
153
+2025-07-21 14:10:41.695
154
+ at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
155
+2025-07-21 14:10:41.695
156
+ at java.lang.reflect.Method.invoke(Method.java:498)
157
+2025-07-21 14:10:41.695
158
+ at com.sie.snest.engine.model.MethodMeta.execute(MethodMeta.java:274)
159
+2025-07-21 14:10:41.695
160
+ at com.sie.snest.engine.model.MethodMeta.invoke(MethodMeta.java:204)
161
+2025-07-21 14:10:41.695
162
+ at com.sie.snest.engine.api.distributed.RpcInvocationV2.invoke(RpcInvocationV2.java:168)
163
+2025-07-21 14:10:41.695
164
+ at com.sie.snest.engine.data.RecordSet.call(RecordSet.java:361)
165
+2025-07-21 14:10:41.695
166
+ at com.sie.iiot.apps.taskscheduler.model.main.TaskScheduler.executeRealTimeTask(TaskScheduler.java:775)
167
+2025-07-21 14:10:41.695
168
+ at com.sie.iiot.apps.taskscheduler.model.main.TaskScheduler.lambda$realTimeTaskBase$0(TaskScheduler.java:95)
169
+2025-07-21 14:10:41.695
170
+ at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
171
+2025-07-21 14:10:41.695
172
+ at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
173
+2025-07-21 14:10:41.695
174
+ at java.lang.Thread.run(Thread.java:748)
175
+2025-07-21 14:10:41.695
176
+ownerThread current state is RUNNABLE, current stackTrace
177
+2025-07-21 14:10:41.695
178
+ at java.net.SocketInputStream.socketRead0(Native Method)
179
+2025-07-21 14:10:41.695
180
+ at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
181
+2025-07-21 14:10:41.695
182
+ at java.net.SocketInputStream.read(SocketInputStream.java:171)
183
+2025-07-21 14:10:41.695
184
+ at java.net.SocketInputStream.read(SocketInputStream.java:141)
185
+2025-07-21 14:10:41.695
186
+ at java.net.SocketInputStream.read(SocketInputStream.java:127)
187
+2025-07-21 14:10:41.695
188
+ at redis.clients.jedis.util.RedisInputStream.ensureFill(RedisInputStream.java:202)
189
+2025-07-21 14:10:41.695
190
+ at redis.clients.jedis.util.RedisInputStream.readByte(RedisInputStream.java:46)
191
+2025-07-21 14:10:41.695
192
+ at redis.clients.jedis.Protocol.process(Protocol.java:126)
193
+2025-07-21 14:10:41.695
194
+ at redis.clients.jedis.Protocol.read(Protocol.java:192)
195
+2025-07-21 14:10:41.695
196
+ at redis.clients.jedis.Connection.readProtocolWithCheckingBroken(Connection.java:316)
197
+2025-07-21 14:10:41.695
198
+ at redis.clients.jedis.Connection.getUnflushedObjectMultiBulkReply(Connection.java:282)
199
+2025-07-21 14:10:41.695
200
+ at redis.clients.jedis.JedisPubSub.process(JedisPubSub.java:135)
201
+2025-07-21 14:10:41.696
202
+ at redis.clients.jedis.JedisPubSub.proceed(JedisPubSub.java:125)
203
+2025-07-21 14:10:41.696
204
+ at redis.clients.jedis.Jedis.subscribe(Jedis.java:7908)
205
+2025-07-21 14:10:41.696
206
+ at com.sie.iiot.apps.redis.model.RedisUtils.subscribe(RedisUtils.java:2397)
207
+2025-07-21 14:10:41.696
208
+ at com.sie.iiot.apps.redis.model.RedisUtils$$EnhancerByCGLIB$$6461d573.CGLIB$subscribe$72(<generated>)
209
+2025-07-21 14:10:41.696
210
+ at com.sie.iiot.apps.redis.model.RedisUtils$$EnhancerByCGLIB$$6461d573$$FastClassByCGLIB$$4ad4bcdf.invoke(<generated>)
211
+2025-07-21 14:10:41.696
212
+ at net.sf.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
213
+2025-07-21 14:10:41.696
214
+ at com.sie.snest.engine.model.ModelInterceptor.intercept(ModelInterceptor.java:84)
215
+2025-07-21 14:10:41.696
216
+ at com.sie.iiot.apps.redis.model.RedisUtils$$EnhancerByCGLIB$$6461d573.subscribe(<generated>)
217
+2025-07-21 14:10:41.696
218
+ at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
219
+2025-07-21 14:10:41.696
220
+ at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
221
+2025-07-21 14:10:41.696
222
+ at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
223
+2025-07-21 14:10:41.696
224
+ at java.lang.reflect.Method.invoke(Method.java:498)
225
+2025-07-21 14:10:41.696
226
+ at com.sie.snest.engine.model.MethodMeta.execute(MethodMeta.java:274)
227
+2025-07-21 14:10:41.696
228
+ at com.sie.snest.engine.model.MethodMeta.invoke(MethodMeta.java:204)
229
+2025-07-21 14:10:41.696
230
+ at com.sie.snest.engine.api.distributed.RpcInvocationV2.invoke(RpcInvocationV2.java:168)
231
+2025-07-21 14:10:41.696
232
+ at com.sie.snest.engine.data.RecordSet.call(RecordSet.java:361)
233
+
234
+2025-07-21 14:10:41.696
235
+ at com.sie.iiot.apps.base.model.deployment.BaseDeployment.init(BaseDeployment.java:29)
236
+2025-07-21 14:10:41.696
237
+ at com.sie.iiot.apps.base.model.deployment.BaseDeployment$$EnhancerByCGLIB$$7b8e4b18.CGLIB$init$5(<generated>)
238
+2025-07-21 14:10:41.696
239
+ at com.sie.iiot.apps.base.model.deployment.BaseDeployment$$EnhancerByCGLIB$$7b8e4b18$$FastClassByCGLIB$$fb1ca8f7.invoke(<generated>)
240
+2025-07-21 14:10:41.696
241
+ at net.sf.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
242
+2025-07-21 14:10:41.696
243
+ at com.sie.snest.engine.model.ModelInterceptor.intercept(ModelInterceptor.java:84)
244
+2025-07-21 14:10:41.696
245
+ at com.sie.iiot.apps.base.model.deployment.BaseDeployment$$EnhancerByCGLIB$$7b8e4b18.init(<generated>)
246
+2025-07-21 14:10:41.696
247
+ at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
248
+2025-07-21 14:10:41.696
249
+ at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
250
+2025-07-21 14:10:41.696
251
+ at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
252
+
253
+```
254
+
255
+
256
+## 4. 解决方式
257
+如果是在线程中执行了SQL操作,那么需要业务代码自己手动的去创建meta和显示的调用 meta.close()
258
+
259
+请参考: [03.meta上下文使用规范](http://192.168.175.198:10001/iidpwiki/01.%E5%BC%80%E5%8F%91%E6%89%8B%E5%86%8C/06.%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98QA/03.meta%E4%B8%8A%E4%B8%8B%E6%96%87%E4%BD%BF%E7%94%A8%E8%A7%84%E8%8C%83.md)
260
+
261
+