Drools内存溢出问题排查

2021-07-01  本文已影响0人  淡淡的小番茄

规则DRL

写了个简单个规则DRL文件,规则信息使用代码生成,数量为10000。此规则对应我们业务场景的数据转发流程,非常有代表性。就是对数据进行账户、产品key、是否属于某个标签的过滤,脚本如下:

package drools.example;

import org.drools.example.api.namedkiesession.Message;

function int hasProductLabels(String deviceLabels,String labels){

  return deviceLabels.indexOf(labels)==-1?0:1;

}

rule "g1_mytest"

when

$msg : Message(orgId =='11111' && productKey=='cu3im1kts3rz8dSc')

&& eval(hasProductLabels('101,102,103',$msg.getProductLabels())>0)

then

end

rule "g1_mytest1"

when

$msg : Message(orgId =='11111' && productKey=='cu3im1kts3rz8dSc')

&& eval(hasProductLabels('101,102,103',$msg.getProductLabels())>0)

then

end

...

规则执行

数据转发示例代码如下:

int n = 1000000000;

long tt = 0;

int num = 0;

while(n-->0) {

long a = System.currentTimeMillis();

Message msg = new Message();

...

session.insert(msg);

int i = session.fireAllRules();

b = System.currentTimeMillis();

tt += (b-a);

System.out.println("触发规则数:"+i+",耗时:"+(b-a)+",执行次数:"+(num++));

}

运行一段时间后出现内存溢出:

问题排查

1、使用jstat查看内存回收情况

jstat -gcutil 21723 1000 1000

GC日志:

发现频繁fullgc,程序存在内存泄露。

2、jmap查看class内存情况

jmap dump:format=b,file=71dump.bin 23216,dump文件一般耗时比较多,直接通过-histo来查看class的内存情况。

jmap -histo 21723 > histo.txt

说明代码中有内存泄露,由于使用的Drools框架,初步定位为:对drools使用不恰当。结合报错信息发现创建的RuleTerminalNodeLeftTuple类不释放。查看相关资料发现需要手动释放FactHandle,代码修改如下:

int n = 1000000000;

long tt = 0;

int num = 0;

while(n-->0) {

long a = System.currentTimeMillis();

Message msg = new Message();

...

FactHandle fact =  session.insert(msg);

int i = session.fireAllRules();

session.delete(fact);

b = System.currentTimeMillis();

tt += (b-a);

System.out.println("触发规则数:"+i+",耗时:"+(b-a)+",执行次数:"+(num++));

}

结论

修改后代码运行平稳,运行1个小时,未发生一次fullgc,内存稳定在1g左右。

上一篇下一篇

猜你喜欢

热点阅读