Apparent connection leak detected问题排查
定位:
- 华为云服务器日志上搜索该异常,日志如下(#1),观察日志后主要看到 连接泄漏发生在 SupplierProductFileOpsAppService.readDataFromExcelAttach()方法中,打印的线程名:TyFileOpsThread-Attachworker-5
- 在发现该方法的问题后定位系统代码,发现最外层加了事务注解,代码主要是 解析Excel,业务操作,更新 tyfile文件状态信息这些事
- hikari 配置项参数(#2)
- 通过配置项知道了我们的连接被占用的超时时间为6秒,所以考虑到是不是任务执行过长导致连接超时,于是加入日志后发现:(#3)
- 整个任务执行耗时几乎全部被业务逻辑占用了,数据量上来后当然会超过6秒,就会被监测到打印连接异常
解决:
- 优化业务逻辑代码
- 适当提高监测超时时间(leak-detection-threshold: 60000)
补充:
此次排查虽然没有发现明显的代码层面的问题,但给了我们一定的排查思路,我们是业务逻辑耗时较长,如感觉业务逻辑没那么复杂但依旧存在此问题,那可能需要看一下除了业务逻辑外的其他操作是否耗时较长,考虑将业务逻辑和文件IO等隔离开,业务逻辑放在一个事务中
#1
2025-06-04 11:04:15.573 [HikariPool-1 housekeeper] [31mWARN[0;39m [traceId = ] [srcapp = ] [c.z.hikari.pool.ProxyLeakTask.run:84] - Connection leak detection triggered for com.mysql.cj.jdbc.ConnectionImpl@5fd6c78e on thread TyFileOpsThread-Attachworker-5, stack trace follows
-2
2025-06-04 11:04:15.573 [HikariPool-1 housekeeper] [31mWARN[0;39m [traceId = ] [srcapp = ] [c.z.hikari.pool.ProxyLeakTask.run:84] - Connection leak detection triggered for com.mysql.cj.jdbc.ConnectionImpl@5fd6c78e on thread TyFileOpsThread-Attachworker-5, stack trace follows
-1
java.lang.Exception: Apparent connection leak detected
0
java.lang.Exception: Apparent connection leak detected
1
at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:128)
2
at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:128)
3
at org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:265)
4
at org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:265)
5
at org.springframework.transaction.support.AbstractPlatformTransactionManager.startTransaction(AbstractPlatformTransactionManager.java:400)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750)
19
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:692)
20
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:692)
21 at com.ehsy.app.productsupply.executor.job.ProductSupplyUploadHandleJob.doHandle(ProductSupplyUploadHandleJob.java:52)
24
at com.ehsy.app.productsupply.executor.job.ProductSupplyUploadHandleJob.doHandle(ProductSupplyUploadHandleJob.java:52)
25
at com.ehsy.app.fileops.executor.job.AbstractAttachHandleJob.execute(AbstractAttachHandleJob.java:26)
26
at com.ehsy.app.fileops.executor.job.AbstractAttachHandleJob.execute(AbstractAttachHandleJob.java:26)
27
at com.ehsy.app.fileops.executor.worker.TyFileOpsRecordAttachWorker.doUpload(TyFileOpsRecordAttachWorker.java:160)
28 at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
36
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
37
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
38
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
39
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
44
47
at java.lang.Thread.run(Thread.java:750)
48
at java.lang.Thread.run(Thread.java:750)
#2
hikari:
auto-commit: true
connection-timeout: 60000 #连接的最大等待时间(毫秒)作用: 在连接池中没有可用连接时,客户端等待连接可用的时间。超时则抛出 SQLException。
idle-timeout: 60000 #空闲连接在被回收之前允许保持空闲状态的最长时间(毫秒) 作用: 如果连接空闲时间超过这个值,且当前空闲连接数超过 minimum-idle,则这个连接会被关闭。
leak-detection-threshold: 6000 #启用连接泄露检测,连接泄露检测阈值为6秒,任何超过6秒连接占用将被记录,有助于找到没有正确关闭连接的代码路径
max-lifetime: 6000 #连接池中每个连接允许存活的最长时间(毫秒) 作用: 任何连接在池中存活时间超过这个值后都会被回收,即使它没有处于空闲状态。
maximum-pool-size: 20 #连接池中允许的最大连接数 作用: 限制连接池中同时存在的最大连接数。超过这个数量的连接请求将被阻塞或超时。
minimum-idle: 10 # 连接池中保持的最小空闲连接数,作用: 确保连接池中至少有这么多空闲连接。即使没有连接请求,也会保持这个数量的连接处于空闲状态。
#3
开始处理Excel附件,业务类型: SUPPLIER_PRODUCT_PURCHASE_PRICE, 附件ID: 1928359950445105153
业务处理完成,耗时: 271250ms
处理结束,总耗时: 271507ms | 业务类型: SUPPLIER_PRODUCT_PURCHASE_PRICE, 附件ID: 1928359950445105153