我在文件中有一组流口水规则,预计会在 Java 对象的多个字段上触发。 一项特定规则不会在生产中随机触发。 我尝试通过模拟产品负载来重现,但它不可重现。
场景:
Default valube city = London
规则:
If Name = John
then set City = Sydney
问题:
Name = John
City = London
//如果基于 drl 文件正确执行规则则预期悉尼
实施:
我正在使用 ExecuterService 和大小为 2 的 FixedThreadPool。
在传递给 ExecuterService
call()
的 Callable 的 submit()
内部,
我正在创建大小为 3 的 ConcurrentLinkedQueue
的 KieSession。
规则文件在此处传递给 KieSession 构造函数。
我的分析:
我认为这个问题与多线程和同步有关。
由于 KieSession 对象是在线程之间共享的,这会导致这样的问题吗?
或者 Drool 规则是否存在我可能不知道的已知问题?
如果有人有任何线索请告诉我。
提前致谢
我要检查的事情。
与
execute(Runnable command)
不同,submit(Callable<T> task)
会捕获任何可投掷物并将其设置到内部字段中。您一定不要忘记执行 Future#get()
来显示后台发生的任何异常,否则没有人会注意到中断您的 Callable
的错误。或者您可以使用execute
,异常将杀死线程并出现在系统错误日志中。
您提到“随机行为”,我想到的唯一随机性是,drools 没有表现出预测的顺序,因为 then 会阻止具有相同显着性的规则执行。规则之间是否存在依赖关系,并且一个规则创建了导致另一规则无法启动的条件?由于流口水的随机性,然后阻止执行,这种情况很少发生。
当然,您有责任确保您的类是线程安全的,并以线程安全的方式访问数据。默认情况下,
fireAllRules()
将执行 then
的同一线程会阻塞。但是,如果您创建多个线程,则必须考虑 Bean 和数据的线程安全性,(通常)而不是考虑流口水本身。我看到默认城市是伦敦,并且它并不总是通过(并行?)线程更新。你的情绪不稳定,不是吗?
写一个测试。你无法修复无法重现的东西。即使是间歇性问题也可以通过负载或压力测试来重现。
我们最终遇到了与上面类似的相同问题,这取决于您创建 kiesession 的方式。我对上述问题陈述的建议是:
全局创建 KieContainer(一次或如果在运行时更新任何规则)。
protected void createKieContainer() { KieModule kiemodule = getKieModule(); kiecontainer = kieservices.newKieContainer(kiemodule.getReleaseId()); }
从 kiecontainer 使用中创建 Kiesession 并销毁它。
KieSession kiesession = kiecontainer.newKieSession();
// 将Bean注入到Drools会话中 DroolsBeanFactory droolsBeanFactory = new DroolsBeanFactory(applicationContext); 尝试{ kiesession.setGlobal("beanFactory", droolsBeanFactory); } 捕获(异常e){ e.printStackTrace(); } FactHandle factHandle = kiesession.insert(entityContext); kiesession.getAgenda().getAgendaGroup(agendaName).setFocus(); kiesession.delete(factHandle); kiesession.dispose();
别忘了
处置
基斯会议