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

Java Drools6整合Spring4 REST调用超时与内存溢出问题求助

Drools调用卡住及内存溢出问题排查与解决方案

核心问题根因

  • 你使用了全局单例的StatefulSession(有状态会话),该对象本身非线程安全,多并发REST请求调用时会出现线程竞争、锁等待,直接导致请求卡住无响应。
  • 每次请求插入的request、response对象在规则执行完成后没有被清理,所有历史请求的对象都永久滞留在会话内存中,请求量上来后直接触发内存溢出。
  • 当前使用的PackageBuilder、RuleBase属于Drools 5版本遗留的废弃API,本身存在潜在内存泄漏风险。

解决方案

1. 优先选用无状态会话适配REST场景

REST接口本身是无状态场景,直接替换为StatelessKieSession即可,该对象线程安全,执行完规则后会自动清理所有插入的Fact对象,无需手动维护状态:

// 全局仅初始化一次KieBase(线程安全,可共享)
private KieBase kieBase;

public RuleEvaluationResponse evaluateRule(RuleEvaluationRequest request) {
    RuleEvaluationResponse response = new RuleEvaluationResponse();
    StatelessKieSession session = kieBase.newStatelessKieSession();
    session.execute(Arrays.asList(request, response));
    return response;
}

2. 若必须使用有状态会话,每次请求单独创建销毁

如果业务需要保留会话状态,绝对不能全局共享单例StatefulSession,每次请求新建会话,执行完成后手动释放资源:

public RuleEvaluationResponse evaluateRule(RuleEvaluationRequest request) {
    RuleEvaluationResponse response = new RuleEvaluationResponse();
    StatefulKieSession session = kieBase.newKieSession();
    try {
        session.insert(response);
        session.insert(request);
        session.fireAllRules();
        return response;
    } finally {
        // 必须调用dispose释放会话所有资源
        session.dispose();
    }
}

3. 替换废弃API使用标准Kie规范

重构初始化逻辑,使用Drools 6版本标准的Kie API构建规则底座,避免废弃API的内存泄漏隐患:

private void initializeDrools() {
    KieServices kieServices = KieServices.Factory.get();
    KieFileSystem kfs = kieServices.newKieFileSystem();
    // 将拼接好的完整规则字符串写入虚拟文件系统
    kfs.write("src/main/resources/rules/completeRules.drl", completeRulesDroolsScript);
    KieBuilder kieBuilder = kieServices.newKieBuilder(kfs).buildAll();
    if (kieBuilder.getResults().hasMessages(Level.ERROR)) {
        log.error("规则构建失败: {}", kieBuilder.getResults().getMessages(Level.ERROR));
        throw new RuntimeException("规则初始化失败");
    }
    KieContainer kieContainer = kieServices.newKieContainer(kieServices.getRepository().getDefaultReleaseId());
    // 全局共享的KieBase仅初始化一次
    this.kieBase = kieContainer.getKieBase();
}

验证方法

  • 每次执行规则后打印会话Fact数量,确认数值不会随请求量持续上涨
  • 接口压测时观测JVM内存占用,确认无持续增长趋势
  • 出现请求卡住时抓取线程栈,确认是否存在Drools会话锁等待

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 21:06:03