You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Drools 7.73.0中如何并行执行DRL规则的LHS逻辑?

解决Drools规则LHS逻辑并行执行的问题

核心误解:multithreadEvaluation的作用

你开启的multithreadEvaluation配置,只负责并行执行规则的RHS(then代码块),而非LHS(when部分)的匹配逻辑。Drools的Rete-OO算法本身是单线程处理模式匹配的,所以即使开启这个配置,LHS里的MyThreadUtil.sleep()依然会串行执行,这就是你调试时看不到LHS并行的原因。

针对LHS耗时操作的并行解决方案

方案1:预加载外部数据(推荐)

既然LHS的耗时来自REST API查询,最稳妥的方式是提前并行查询所有需要的外部数据,将结果作为事实插入KieSession,规则直接匹配内存中的事实即可,完全避免在LHS中执行阻塞操作。

示例代码:

// 并行调用所有需要的REST接口/耗时操作
List<CompletableFuture<Object>> futures = Arrays.asList(
    CompletableFuture.supplyAsync(() -> queryOrderAmount()),
    CompletableFuture.supplyAsync(() -> queryHistoryOrders()),
    // 其他需要的查询...
);
// 等待所有查询完成
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
// 将查询结果插入KieSession
futures.stream()
       .map(CompletableFuture::join)
       .forEach(session::insert);

// 执行规则
session.fireAllRules(new RuleNameStartsWithAgendaFilter("multi_thread_"));

对应的DRL规则可以简化为直接匹配预加载的事实:

rule "multi_thread_1"
    no-loop true
    when
        $orderAmount : OrderAmount() // 匹配预加载的OrderAmount事实
    then
        System.out.println($orderAmount.getValue());
end

方案2:使用Drools异步评估(Async Eval)

如果必须在LHS中处理耗时操作,可以使用Drools的async eval()语法(Drools 7及以上版本支持),将耗时逻辑包装为异步执行,同时需要配置自定义线程池。

修改后的DRL规则:

package multi.thread;
import com.hp.util.MyThreadUtil;

rule "multi_thread_1"
    no-loop true
    when
        $sleepTime1 : Integer() from async eval(MyThreadUtil.sleep())
    then
        System.out.println($sleepTime1);
end

同时需要在KieBase配置中指定异步线程池:

KieBaseConfiguration kbaseConfig = kieServices.newKieBaseConfiguration();
// 设置异步评估的线程池大小
kbaseConfig.setOption(AsyncEvaluationOption.get(true));
kbaseConfig.setOption(ThreadPoolOption.get(new ThreadPoolConfiguration()
                       .setCorePoolSize(4)
                       .setMaxPoolSize(8)));
KieBase kieBase = kieContainer.newKieBase(kbaseConfig);
KieSession session = kieBase.newKieSession();

方案3:多KieSession并行执行(规则完全独立场景)

如果你的100个规则完全独立(无共享事实、无规则间依赖),可以将规则分组,每组用独立的KieSession,通过线程池并行执行各组规则。

示例代码:

// 定义规则分组
List<List<String>> ruleGroups = Arrays.asList(
    Arrays.asList("multi_thread_1", "multi_thread_2"),
    Arrays.asList("multi_thread_3", "multi_thread_4")
);

ExecutorService executor = Executors.newFixedThreadPool(2);
// 并行执行每组规则
for (List<String> group : ruleGroups) {
    executor.submit(() -> {
        KieSession session = kieContainer.newKieSession();
        session.fireAllRules(new RuleNameMatchesAgendaFilter(String.join("|", group)));
        session.dispose();
    });
}
executor.shutdown();
executor.awaitTermination(1, TimeUnit.MINUTES);

总结

  • 优先选择预加载外部数据,这是最稳定且性能最优的方案,避免Drools内部异步逻辑的复杂性。
  • 若必须在LHS处理,使用async eval()并配置合适的线程池。
  • 规则完全独立时,可以用多KieSession并行执行。

内容的提问来源于stack exchange,提问作者linhongpeng

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 01:02:42