起因
基于一些原因,需要将kettle6.1升级到新版的kettle8.2。升级后发现kettle8每隔几天出现
GC overhead limit exceeded 或者 OutOfMemoryError:Java heap space;
一开始猜测kettle8为了提高性能,而牺牲更多的堆内存,便从开始的Xmx2048m 增加到 Xmx4096m.
可是没过几天还是一样出现问题,又从4096m增加到6144m.
问题依旧得不到解决.
通过排查日志发现内存溢出的问题发现: 定时重复执行的作业出现数据库连接不上,
导致好几天的作业一直都在报错数据库连接拒绝,一直到内存溢出,kettle奔溃.
排查发现,只要作业是正常执行,kettle8.2就不会出现内存溢出的问题.
但是只要有作业一直报异常,那么只要1-2天(也可能更短,看作业执行频率),
kettle8.2就会内存溢出挂掉,
kettle6.1不会出现此种情况.
场景重现
测试环境部署kettle8.2,模拟重现.
在kettle8.2 启动脚本增加
-Dcom.sun.management.jmxremote.port=9008 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false
本地jconsole可以远程实时监控kettle运行时的内存与线程情况
增加
-Xdebug -Xrunjdwp:transport=dt_socket,address=5005,server=y,suspend=n
本地idea可以远程debug
在idea中git clone kettle8.2的源码.
往kettle上发了10个作业,每隔5秒重复执行.其中9个作业是正常执行的,
1个作业连接一个不存在的数据库,会一直报连接拒绝错误
jconsole监控如下图
红框时间区间是该错误job停用的时间段,期间内存能维持稳定。
在测试服务器上使用命令jmap -heap,发现老年代内存居高不下,无法回收。
排查
再使用命令jmap -histo:live >> a.log(JVM会先触发gc)排查哪些对象没有被回收
327 83712 org.pentaho.di.trans.Trans
327 20928 org.pentaho.di.trans.steps.selectvalues.SelectValuesMeta
327 20928 org.pentaho.di.trans.steps.tableinput.TableInputMeta
327 31392 org.pentaho.di.trans.steps.insertupdate.InsertUpdateMeta
866 27712 org.pentaho.di.trans.TransHopMeta
基本上可以断定是每次错误执行的作业中的转换(trans)没有被GC回收。
但是仅根据堆内存中的对象数量无法判断是哪里还在引用这些对象。
使用命令 jmap -dump:live,format=b,file=./dump.dat 生成内存镜像
使用命令 jhat -J-Xmx1024M ./dump.dat (jdk自带分析工具)
执行后等待console 中输入start HTTP server on port 7000 即可使用浏览器访问 IP:7000
随机查看了几个引用trans对象的对象,看不出什么
kettle的对象互相引用太多太复杂,jhat这个工具很难直观找到最上层的引用对象
下载dump文件到本机,使用eclipse的插件 memory anaylize 分析dump
如下图
在树形图上容易trans对象没有被回收是因为被最上层的HashMap引用
在树形图中找到容易定位问题代码对象是
org.pentaho.osgi.blueprint.collection.utils.ServiceMap
查看源码,猜测作业执行异常的情况,没有执行itemRemoved方法,导致本该被回收的对象在内存越积越多
在源码中新增、修改两个方法打上断点,开启远程debug 如下图
调试一个正常的作业和错误的作业,发现确实如推测的,执行报错的作业最终没有执行itemRemoved.
调试过程跳过
定位具体代码 org.pentaho.di.trans.Trans
public void execute( String[] arguments ) throws KettleException { prepareExecution( arguments ); startThreads(); }
正常执行的job 会在 prepareExecution方法中的transMeta.setEmbeddedMetastoreProviderKey(....)
中调用serviceMap的itemAdded()
并在startThreads()方法中的transMeta.disposeEmbeddedMetastoreProvider()中
调用serviceMap的itemRemoved()
异常的job会在prepareExecution方法中初始化step时抛出数据库连接异常,导致后续不会进入到startThreads().
这下内存溢出的问题明确了,稍微修改源码,打包替换原先的kettle-engine.8.2.0.jar.
至此,kettle8.2内存泄漏问题彻底解决
相关推荐
1. **大数据量处理**:当Kettle处理大量数据时,如在表输入、表输出、聚合、Join、过滤等步骤中,如果一次性加载太多数据到内存,可能会超出JVM的堆内存限制。 2. **内存管理不当**:Kettle的默认配置可能不适合特定...
Kettle是一款开源的数据集成工具,也被称为Pentaho Data Integration(PDI),它提供了强大的ETL能力。本文将深入探讨如何在Kettle中实现步骤的循环执行,以满足重复处理数据的需求。 标题"Kettle实现步骤循环执行...
在这个项目中,Kettle被用来生成一亿条信用卡号模拟数据,并将这些数据成功地导入到Oracle数据库中,同时避免了常见的内存溢出问题。 【描述】提到的"生成了一亿条信用证卡号"展示了Kettle在生成测试数据方面的强大...
需要注意的是,处理大量数据时,应合理优化SQL查询,避免内存溢出,同时监控Job和Transformation的性能,以确保高效运行。 通过深入理解Kettle的Job和Transformation之间的数据交互机制,以及如何使用"作业循环...
在大数据环境中,一次性加载所有数据通常是不可行的,因为它可能导致内存溢出或系统性能下降。动态分页允许我们按需逐页处理数据,减少一次性处理的数据量。在Kettle中,这可以通过创建一个工作流或者转换来实现,...
同时,合理配置Kettle的内存使用,避免内存溢出。 综上,Java集成Kettle执行作业文件是利用Kettle的强大ETL能力,结合Java的灵活性和控制力,实现数据处理任务的自动化执行。通过这种方式,可以构建复杂的数据管道...
在测试并行作业时,可能会出现内存溢出错误,甚至会出现资源消耗过大导致系统不稳定的现象。深入研究发现,pan和kitchen在执行过程中会不断初始化Kettle环境,这不仅耗时也消耗大量资源。 最后,通过Java代码直接...
- **数据分块**:对于大数据量,可以考虑分块处理,每次处理一部分数据,避免一次性加载大量数据导致内存溢出。 - **性能监控**:通过日志和性能监控工具跟踪Kettle作业运行情况,找出瓶颈并进行优化。 综上所述,...
Kettle,又称Pentaho Data Integration(PDI),是一款强大的ETL(Extract, Transform, Load)工具,广泛应用于数据仓库和大数据处理项目中。它提供了图形化的界面,使得数据抽取、转换和加载过程变得直观易懂,非常...
在实际使用过程中,可能会遇到一些常见问题,例如连接配置错误、SQL语法错误、内存溢出等。因此,了解Kettle的错误日志和调试机制至关重要,以便快速定位并解决问题。同时,配合SQL脚本和预定义的工作流文件(kjb、...
2. **OOM问题**:大量数据可能导致内存溢出。可以通过调整Kettle的工作线程、增加内存分配或优化数据处理策略来防止。 3. **数据同步遗漏**:定时轮询策略可能错过实时数据。为解决这个问题,可以调整轮询间隔,或者...
- 若遇到栈溢出错误(StackOverFlowError),可添加`-Xss`参数并根据本机内存配置进行适当调整。 #### 五、KETTLE_HOME环境变量设置 - **作用**:`.kettle`文件夹用于存储Kettle的各种配置文件,默认位于C盘用户...
关于Java中内存溢出的解决办法 关于Java中内存溢出的解决办法
- 修改Spoon.bat配置,防止内存溢出和编码问题。 - 运行Spoon.bat启动工具,利用转换和作业功能构建数据流。 - 表输入和输出节点用于读写数据,配置数据库连接,根据需求编写SQL或设置字段映射。 2. Linux环境下...
### Java大数据案例_6Hive、Kettle #### 安装部署Hive **知识点概述:** 本案例涉及的关键技术包括Hive的安装与配置、Hive的基本操作以及Hive与MapReduce的集成使用。Hive是一种数据仓库工具,可以方便地对存储在...
1. **读取Excel**:使用Apache POI等库读取Excel文件,可以逐行或按需加载数据,避免一次性加载整个文件导致内存溢出。 2. **预处理数据**:在读取数据后,可能需要进行数据清洗、格式转换等预处理步骤,以符合...
在Java 8之前的版本,这部分内存被称为永久代,容易因类数量过多而引发内存溢出。而元空间使用本地内存,通过MetaspaceSize和MaxMetaspaceSize两个参数来控制其大小,从而解决了永久代可能导致的溢出问题。 Java的...
从给定的文件信息来看,主要涉及的是Kettle这一数据集成工具中的转换控件及其功能。Kettle,也称为Pentaho Data Integration (PDI),是开源数据集成平台的一部分,用于执行ETL(Extract, Transform, Load)操作,即...