Skip to content

[BUG] PgConnection连接未释放,内存泄露问题 #4181

Description

@zhaoguangqin

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

导出hertzbeat dump文件,分析如下:

📊 Java内存占用分析报告

类名 实例数量 自身大小 总大小
byte[] 396,159 49.56 MB >= 49.56 MB
org.postgresql.jdbc.PgConnection 819 0.10 MB >= 38.84 MB
java.lang.ref.Finalizer 1,149 0.04 MB >= 38.41 MB
java.lang.Object[] 59,737 6.01 MB >= 30.34 MB
java.util.concurrent.ConcurrentHashMap 5,735 0.35 MB >= 26.61 MB
java.util.concurrent.ConcurrentHashMap$Node[] 3,296 1.54 MB >= 26.31 MB
java.lang.String 377,327 8.64 MB >= 25.11 MB
java.util.HashMap$Node[] 41,292 5.56 MB >= 24.98 MB
java.util.HashMap 22,951 1.05 MB >= 24.38 MB
java.util.concurrent.ConcurrentHashMap$Node 125,723 3.84 MB >= 23.15 MB
java.util.ArrayList 29,540 0.68 MB >= 22.96 MB
java.util.HashMap$Node 467,433 14.26 MB >= 19.48 MB
org.postgresql.core.v3.QueryExecutorImpl 819 0.17 MB >= 18.77 MB
org.postgresql.jdbc.TypeInfoCache 819 0.07 MB >= 18.36 MB
java.util.zip.ZipFile$Source 437 0.03 MB >= 17.49 MB

📝 表格说明

  1. 类名:Java类的全限定名
  2. 实例数量:该类在内存中的实例个数
  3. 自身大小:所有实例本身占用的内存大小(不包括引用的对象)
  4. 总大小:所有实例及其引用对象占用的总内存大小

PgConnection 的对象高达819个,占用38MB的空间,随着时间的增长还会越来越多
查看持有PgConnection对象的引用如下:

📊 PostgreSQL连接对象内存占用分析

Class Name Objects Shallow Heap
org.postgresql.jdbc.PgConnection 819 0.10 MB
├─ org.postgresql.jdbc.TypeInfoCache 819 0.07 MB
├─ org.postgresql.jdbc.PgPreparedStatement 457 0.05 MB
├─ java.lang.ref.Finalizer 819 0.03 MB
└─ com.zaxxer.hikari.pool.PoolEntry 10 0.00 MB
Total 4 entries

从上可以看出,819个PgConnection处于未关闭,对象一直未释放

📊 问题定位

JdbcCommonCollect类中,getConnection方法

Connection connection = DriverManager.getConnection(url, username, password);

三条泄漏路径

1.高并发下的竞争条件(主要原因):多个采集线程同时对同一目标发起 getCache() → 都 miss → 各自创建新连接 → 只有最后一个进缓存,其余的连接永远不会被关闭
2.reuseConnection=true + 异常路径:DriverManager.getConnection() 部分建立连接后抛出异常,连接对象已创建但 connection 变量从未赋值,无法 close
3.缓存 key 失效后的连接泄漏:缓存 600 秒超时后,cleanTimeoutOrUnHealthyCache 移除旧连接,但在移除和重建之间的并发窗口内可能产生孤儿连接

修改方案

改为 per-target HikariCP DataSource:把 GlobalConnectionCache 中存的 JdbcConnect(Connection) 改为存 HikariDataSource,从池中借还,彻底绑回 Hikari 管理

经过上述修改,PgConnection连接数得到有效控制,内存不在疯长

Expected Behavior

No response

Steps To Reproduce

No response

Environment

HertzBeat version(s):1.8.0

Debug logs

No response

Anything else?

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    Status
    To do

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions