环境:windows7,jvm内存设置14G,kettle5.1后来升级到5.4,oracle作为资源库。
问题背景:我们通过web页面管理kettle的job运行,这只是一个管理界面,即使web项目停掉也不会影响job的运行情况,实际运行job的是后台程序,随着job数量的增多,达到三四百个时,job的运行速度也达到了难以接受的程度。
方案1:
针对出现的问题,经测试发现,job一经运行就不会再重新从资源库读取了(针对定时运行的job),job中的转换则每次都会重新从资源库中读取,我找到了org.pentaho.di.job.entries.trans.JobEntryTrans这个类,这是一个作业控件,代表一个转换,调试跟踪代码就会发现他确实会在每次运行时重新读取资源库加载转换,因为kettle每次运行时都是克隆了这个控件,然后运行时重新加载,具体还是调试跟踪代码才能更清楚的了解,对于他为什么要克隆,我也不是很了解,当然也不敢乱动相关代码,估计因为里面有些状态属性吧。
解决问题的思路是尽量从底层,具体的问题点解决问题,一开始就想过优化具体读取转换的过程,但没有去尝试,而是采用了更具针对性,更简单的方式,在JobEntryTrans这个类里面建了个静态Map,用于缓存读取过的转换,这个缓存的生命周期与对应的job差不多,因为每次从数据库读取JobEntryTrans这个控件时,都会清除该控件引用的转换的缓存,若多个job都引用了这个转换,那他的生命周期比job还短。
这个方案需要改的代码量很小,读取转换时,先查看缓存,没有就读取资源库,然后缓存,下次就直接用缓存了,其次就是在JobEntryTrans类的读取资源库的方法中加上清除对应转换缓存的代码。
缓存??到底以什么形式缓存?为了尽量减小对原有逻辑的影响我先缓存了xml,就是调用了TransMeta的getXml方法,下次读取时就直接使用xml,这个方式在测试环境是没问题的,但在正式环境中始终有个转换有问题,运行异常,正式环境不方便调试,于是我就改为直接缓存TransMeta对象,每次就直接用了,这对写代码来说肯定更简单了,但这个对象里面到底有哪些东西,我没有精力去仔细分析,抱着试一试的态度实现了,经测试效果还是很不错的,缓存xml时的问题不存在了,经过一段时间的运行,没有发现什么大问题,就是记录的日志感觉有点问题,该方案现在依然在使用中,基本没有影响kettle完成它的工作。
这个代码量不大,就贴出来,就是修改了kettle5.4中TransMeta这个类的两个方法:
// Load the jobentry from repository // public void loadRep( Repository rep, IMetaStore metaStore, ObjectId id_jobentry, List<DatabaseMeta> databases, List<SlaveServer> slaveServers ) throws KettleException { try