共计 2023 个字符,预计需要花费 6 分钟才能阅读完成。
背景痛点
在业务规则管理系统(BRMS)中,rule 的过度使用常导致维护成本激增。例如,某电商平台的风控系统最初完全基于 Drools 规则引擎实现,随着业务复杂度提升,规则数量从最初的 200 条膨胀到 5000+ 条,引发以下问题:

- 规则加载时间从 2 秒延长到 15 秒
- 平均请求响应时间下降 50%(从 80ms 增加到 160ms)
- 规则冲突检测耗时占整体发布流程的 70%
概念对比
| 维度 | Rule | Skill |
|---|---|---|
| 决策维度 | 离散条件判断(if-then) | 连续能力执行(function) |
| 维护成本 | 低(DRL 配置化) | 高(需编码实现) |
| 执行耗时 | 纳秒级(Rete 算法优化) | 毫秒级(涉及业务逻辑) |
| 适用场景 | 静态业务规则 | 动态业务能力 |
选型标准
采用三维评估模型进行技术选型:
- 条件分支数量
- <10 个:纯 Rule 方案
- 10-20 个:Rule+DSL 组合
-
20 个:Skill 服务化
-
外部依赖程度
- 无外部调用:Rule 优先
-
依赖 DB/API:必须用 Skill
-
变更频率
- 日级变更:Rule 配置化
- 月级变更: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();}
}
性能优化
- Rule 层优化
- 启用 Rete 算法的状态缓存
- 使用 Phreak 模式替代经典 Rete
-
规则按业务域分组加载
-
Skill 层优化
- 线程池隔离:不同技能使用独立线程池
-
超时控制:
@Bean public Executor riskSkillExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(10); executor.setMaxPoolSize(50); executor.setQueueCapacity(1000); executor.setThreadNamePrefix("risk-skill-"); return executor; } -
混合模式熔断
- Rule 执行超时自动降级
- Skill 服务不可用时启用缓存结果
避坑指南
- 规则中的 IO 禁忌
- 错误做法:在 DRL 中调用 JDBC
-
正确方案:将数据预处理为 Fact
-
技能幂等性
- 必须设计 requestId 机制
-
示例:
@Transactional public void processPayment(PaymentRequest request) {if (duplicateCheck(request.getRequestId())) {return; // 幂等处理} // 业务逻辑... } -
版本兼容性
- 规则版本与事实对象版本绑定
- 采用蓝绿发布策略
延伸思考
当规则需要集成机器学习动态调整时,建议:
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 的组合,可以在保持系统灵活性的同时获得最佳性能表现。关键在于根据业务特征选择适当的抽象层级,并建立有效的治理机制。
正文完
