采用Pentaho Kettle 7.1进行约500万条单表数据抽取,在快要抵达胜利的终点时,出现了内存泄漏,java.lang.OutOfMemoryError: Java heap space,竟然是因自己粗心导致
背景
业务场景中需要抓取异构系统中的数据,自然想到了鼎鼎有名开源的ETL工具Kettle,网上说8的版本还有诸多问题,这里采用较老的7.1.0.0.-12
测试场景
1、运行环境
我使用了Kettle的Carte组件,将Kettle进行了Docker容器化打包,在服务器上部署运行,由于是测试,服务器的硬件配置不是特别高
类别 | cpu | 内存 | 磁盘 |
---|---|---|---|
配置 | 2核心 | 4G | 500G |
2、运行的jvm参数
-XX:+AggressiveOpts
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/tmp
-XX:InitialHeapSize=1073741824
-XX:MaxHeapSize=2147483648
-XX:MaxMetaspaceSize=268435456
-XX:+PrintCommandLineFlags
-XX:+PrintGCDateStamps
-XX:+PrintGCDetails
-XX:+UseG1GC
3、运行的JRE版本
openjdk version "1.8.0_111"
OpenJDK Runtime Environment (build 1.8.0_111-8u111-b14-2~bpo8+1-b14)
OpenJDK 64-Bit Server VM (build 25.111-b14, mixed mode)
4、源库的情况
源库为Postgres,目标库也为Postgre,源库中约为590万数据。
5、kettle工程
通过表输入从源表中读取数据,通过插入/更新将数据写入目标库表。
6、运行
通过Kettle spoon连接数据库资源库,提交转换至服务端的Carte运行。
测试结果
1、过多次反复测试发现到处理到500万条记录数时候就开始OutOfMemoryError: Java heap space
2、GCView分析gc.log日志分析如下图
3、Memory Analyzer分析dump文件,提示有内存泄漏
本人对kettle的源码不是特别了解,所以无法继续深入分析,粗略判断org.pentaho.di.core.logging.MetricsRegistry未释放,导致内存持续增长从而OOM。
One instance of "org.pentaho.di.core.logging.MetricsRegistry" loaded by "java.net.URLClassLoader @ 0x800287c8" occupies 2,062,205,928 (96.24%) bytes.
至此,感觉离胜利遥遥在望,但是总是不清楚是哪里有问题导致内存泄漏,不清楚是我使用的问题,还是本身Kettle该版本程序的问题,望各位大佬指点!如果有需要可以提供dump文件供分析。
如果有需要可以提供dump文件供分析,请入群联系索取!
结论
注意,此段为找到原因后补充的内容。
通过反复测试及长时间折腾,最终发现原因后竟哭笑不得,期间尝试过各种方法
- 向pentaho_kettle提交bug,未果
- 怀疑是该版本的问题,对比了github上kettle的7.1大版本后续的版本的代码,尝试寻找是否有对这问题的处理,未果
- 尝试编译7.1系列中最新的版本7.1.0.0-32,验证新版本是否还有此问题,未果
最终在一次偶然的反复验证操作步骤过程中注意到了一个选项的关键字中包含了Metrics,于是立马取消勾选改选项,然后仿佛真的就是这个问题,一切都好了。
如图,该选项在默认的是勾选的(略坑),在执行的时候一定要取消勾选,否则导致内存泄漏。