规则引擎实战:如何正确选择rule与skill的适用场景

2次阅读
没有评论

共计 2023 个字符,预计需要花费 6 分钟才能阅读完成。

image.webp

背景痛点

在业务规则管理系统(BRMS)中,rule 的过度使用常导致维护成本激增。例如,某电商平台的风控系统最初完全基于 Drools 规则引擎实现,随着业务复杂度提升,规则数量从最初的 200 条膨胀到 5000+ 条,引发以下问题:

规则引擎实战:如何正确选择 rule 与 skill 的适用场景

  • 规则加载时间从 2 秒延长到 15 秒
  • 平均请求响应时间下降 50%(从 80ms 增加到 160ms)
  • 规则冲突检测耗时占整体发布流程的 70%

概念对比

维度 Rule Skill
决策维度 离散条件判断(if-then) 连续能力执行(function)
维护成本 低(DRL 配置化) 高(需编码实现)
执行耗时 纳秒级(Rete 算法优化) 毫秒级(涉及业务逻辑)
适用场景 静态业务规则 动态业务能力

选型标准

采用三维评估模型进行技术选型:

  1. 条件分支数量
  2. <10 个:纯 Rule 方案
  3. 10-20 个:Rule+DSL 组合
  4. 20 个:Skill 服务化

  5. 外部依赖程度

  6. 无外部调用:Rule 优先
  7. 依赖 DB/API:必须用 Skill

  8. 变更频率

  9. 日级变更:Rule 配置化
  10. 月级变更:Skill 代码化

混合架构实现

Rule 引擎基础匹配

/**
 * 风控事实对象
 */
@Fact
public class RiskFact {
    private Long userId;
    private BigDecimal paymentAmount;
    // getters/setters...
}

// Drools 规则示例
rule "HighRiskRule"
when
    $fact : RiskFact(paymentAmount > 10000)
then
    insert(new RiskMark("HIGH"));
end

Skill 服务封装

@FeignClient(name = "fraud-service")
public interface FraudDetectionSkill {@PostMapping("/detect")
    RiskResult detect(@RequestBody FraudRequest request);
}

// 策略路由
public class RiskStrategy {
    private final DroolsRuleEngine ruleEngine;
    private final FraudDetectionSkill fraudSkill;

    public RiskLevel evaluate(RiskFact fact) {
        // 先执行规则引擎
        RuleResult ruleResult = ruleEngine.execute(fact);

        if (ruleResult.needDeepCheck()) {
            // 触发技能服务
            return fraudSkill.detect(buildRequest(fact));
        }
        return ruleResult.getLevel();}
}

性能优化

  1. Rule 层优化
  2. 启用 Rete 算法的状态缓存
  3. 使用 Phreak 模式替代经典 Rete
  4. 规则按业务域分组加载

  5. Skill 层优化

  6. 线程池隔离:不同技能使用独立线程池
  7. 超时控制:

    @Bean
    public Executor riskSkillExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(10);
        executor.setMaxPoolSize(50);
        executor.setQueueCapacity(1000);
        executor.setThreadNamePrefix("risk-skill-");
        return executor;
    }

  8. 混合模式熔断

  9. Rule 执行超时自动降级
  10. Skill 服务不可用时启用缓存结果

避坑指南

  1. 规则中的 IO 禁忌
  2. 错误做法:在 DRL 中调用 JDBC
  3. 正确方案:将数据预处理为 Fact

  4. 技能幂等性

  5. 必须设计 requestId 机制
  6. 示例:

    @Transactional
    public void processPayment(PaymentRequest request) {if (duplicateCheck(request.getRequestId())) {return; // 幂等处理}
        // 业务逻辑...
    }

  7. 版本兼容性

  8. 规则版本与事实对象版本绑定
  9. 采用蓝绿发布策略

延伸思考

当规则需要集成机器学习动态调整时,建议:
1. 设计规则特征向量接口

public interface FeatureExtractor {Map<String, Double> extract(RiskFact fact);
}

2. 实现动态权重加载

rule "DynamicRule"
when
    $fact : RiskFact()
    $weights : MLWeights()
then
    double score = calculateScore($fact, $weights);
    // 后续处理...
end

3. 建立 AB 测试流量分流机制

通过合理运用 Rule 与 Skill 的组合,可以在保持系统灵活性的同时获得最佳性能表现。关键在于根据业务特征选择适当的抽象层级,并建立有效的治理机制。

正文完
 0
评论(没有评论)