我在我的项目中使用了drools 6.3.0。我有大约3千条规则,有2个类别。比如说,category1有1500条规则,category2有1500条规则。 有不同数据的20k订单。每个订单都有一组不同的属性。现在,为每个请求创建kiesession需要时间,而且速度非常慢。因此,计划使用相同的kiesession执行所有订单和订单将使用多线程进行处理。
以下是我目前的做法。
KieBase kieBase = null;
KieServices kieServices = KieServices.Factory.get();
KieRepository kieRepository = kieServices.getRepository();
kieRepository.addKieModule(new KieModule() {
@Override
public ReleaseId getReleaseId() {
return kieRepository.getDefaultReleaseId();
}
});
KieFileSystem kfs = kieServices.newKieFileSystem();
kfs.write(******); // Load 3k rules in a for loop
KieBuilder kb = kieServices.newKieBuilder(kfs);
kb.buildAll();
KieContainer kContainer = kieServices.newKieContainer(kieRepository.getDefaultReleaseId());
kieBase = kContainer.getKieBase();
kContainer = kieServices.newKieContainer(kieRepository.getDefaultReleaseId());
kieBase = kContainer.getKieBase();
KieSession kieSession = kieBase.newKieSession();
这就是我创建kiesession的方式,并希望将此kiesession用于所有订单执行。
我想使用线程池并行执行订单。
这就是
//这里的条目基于类别和一些id。 每条规则都有id和category。对于每个id和cateogory,都会有一组应该被评估的规则。
流程就像,
1)从DB获取20k订单
2)对于每个订单,获取要执行的ID
3)对于每个id,格式入口点如entry = id+_category
4)插入订单属性数据和fireRules。
final EntryPoint entryPoint = ksession.getEntryPoint(entry);
if (entryPoint != null) {
entryPoint.insert(data);
ksession.fireAllRules();
} else {
log.warn("No rules to be executed");
}
现在,因为我必须并行执行订单,
每个订单都会在parallal中调用以下代码,
entryPoint.insert(data);
ksession.fireAllRules();
因为,每个订单都有不同的属性并将不同的数据插入入口点,这会导致问题并且无法获得预期的结果。
无论如何要实现这个目标吗?
由于
答案 0 :(得分:0)
不是超级专家,但我正在寻找类似的东西,我认为答案是将这些调用变为同步块...这根本不是并行执行或者是使用改为CloseableIterator<StreamResult<T>>
,它将使用自己的工作内存为执行调用创建一个常规StatelessKieSession
本地,因此它只会传入您传入KieSession
的数据对象。
令人惊讶的是,与重复使用单个常规会话并在触发规则之间清除其中的对象相比,使用无状态会话似乎并不显着更耗时。
答案 1 :(得分:0)
也许您应该使用原型会话。在kmodule.xml文件中添加:
<ksession name="YourSessionName" type="stateful" default="false" clockType="realtime" scope="prototype"/>