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

Drools-engine 8.29.0.Final内存问题:步骤、依赖及占用原因问询

Drools在微服务中的使用疑问与解答

背景说明

我们在微服务中使用Drools,通过UI接收用户定义的规则,经Velocity模板生成DRL文件。规则执行分为两部分(已实现KieBase缓存):

1. KieBase生成与缓存代码

KieHelper kieHelper = new KieHelper();
kieHelper.setClassLoader(this.getClass().getClassLoader());
String drl = "drl";
kieHelper.addContent(drl, ResourceType.DRL );
Results res = kieHelper.verify();
KieBaseConfiguration kbConf = 
KieServices.Factory.get().newKieBaseConfiguration();
kbConf.setOption( EqualityBehaviorOption.EQUALITY );
KieBase kieBase = kieHelper.build( kbConf );

2. 基于缓存KieBase的规则执行代码

KieSessionConfiguration ksConf = KnowledgeBaseFactory.newKnowledgeBase().getSessionConfiguration();
      ((SessionConfiguration) ksConf).setBeliefSystemType(BeliefSystemType.DEFEASIBLE);
      ksConf.setProperty("type", "stateful");
      KieSession kieSession = kieBase.newKieSession();
     
      kieSession.setGlobal("rules", rules);
    
      Collection<KiePackage> kiePackages = kieSession.getKieBase().getKiePackages();
      
      kieSession.insert(request);
      kieSession.insert(response);
    
      try {
        kieSession.fireAllRules();
      }catch( ConsequenceException x ){
        logger.warn( "Consequence exception", x);

      }
      finally {
        kieSession.dispose();
      }

使用的Drools依赖

<dependency>
    <groupId>org.drools</groupId>
    <artifactId>drools-engine</artifactId>
    <version>${drools-engine.version}</version>
</dependency>

<dependency>
    <groupId>org.drools</groupId>
    <artifactId>drools-mvel</artifactId>
    <version>${drools-mvel.version}</version>
</dependency>

<dependency>
    <groupId>org.drools</groupId>
    <artifactId>drools-serialization-protobuf</artifactId>
    <version>${drools-serialization-protobuf.version}</version>
</dependency>
<dependency>
    <groupId>org.drools</groupId>
    <artifactId>drools-xml-support</artifactId>
    <version>${drools-xml-support.version}</version>
</dependency>

技术疑问解答

1. 当前规则执行步骤是否符合规范?

整体方向符合Drools最佳实践,但存在几个细节问题:

  • KieSessionConfiguration创建冗余:无需通过KnowledgeBaseFactory.newKnowledgeBase().getSessionConfiguration()新建KnowledgeBase来获取配置,规范写法是直接用KieServices创建:
    KieSessionConfiguration ksConf = KieServices.Factory.get().newKieSessionConfiguration();
    
  • 无效代码需清理:Collection<KiePackage> kiePackages = kieSession.getKieBase().getKiePackages();如果没有后续业务使用,属于无效操作,建议删除。
  • 多余配置项:KieSession默认就是有状态(stateful)的,无需通过ksConf.setProperty("type", "stateful");显式设置。
  • 合规部分:缓存线程安全的KieBase、每次请求创建新KieSession、在finally块中dispose KieSession,这些都是正确的做法。

2. 使用的Drools依赖是否合适?

依赖配置有优化空间:

  • 版本统一:当前使用多个版本变量管理Drools依赖,容易引发版本冲突,建议统一用一个${drools.version}变量管理所有Drools相关依赖的版本。
  • 冗余依赖清理:
    • drools-serialization-protobuf:仅当需要序列化KieSession或规则对象时才需要,无序列化需求可移除。
    • drools-xml-support:用于支持XML格式规则,若仅使用DRL文件,可移除该依赖。
  • 潜在依赖补充:部分Drools版本中drools-engine未包含DRL编译模块,若运行时出现编译相关错误,需添加drools-compiler依赖。

3. 为何内存占用过高(20GB容器中内存占比达95%),已做缓存仍无改善?

缓存KieBase仅解决重复编译的内存消耗,内存过高可能由以下原因导致:

  • KieBase缓存堆积:如果用户频繁修改规则,每次修改生成新KieBase,旧实例未及时从缓存中清理,会导致大量KieBase堆积占用内存,需设置缓存淘汰策略(如过期时间、数量上限)。
  • KieSession相关问题:
    • 高并发场景下短时间创建大量KieSession,JVM GC可能无法及时回收已dispose的实例,导致内存临时飙升。
    • 插入KieSession的request/response对象过大,或被其他线程/缓存持有引用,即使KieSession被dispose,这些业务对象也无法被GC回收。
  • 规则本身的问题:
    • 规则数量过多、条件过于复杂(如嵌套大量循环),会导致KieBase内存占用剧增。
    • 规则执行过程中生成大量临时中间对象,未及时清理引发内存堆积。
  • JVM配置问题:容器内存20GB但JVM堆内存设置不合理(过大导致GC压力大,过小引发频繁Full GC),都会导致内存占用异常。
  • 内存泄漏:需通过JProfiler、VisualVM等工具抓取内存快照,排查是否存在KieBase、KieSession或业务对象的内存泄漏(如静态引用未释放、监听器未注销)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 16:54:51