這五種規(guī)則引擎,真香!
前言
核心痛點(diǎn):業(yè)務(wù)規(guī)則高頻變更與系統(tǒng)穩(wěn)定性之間的矛盾。
想象一個(gè)電商促銷(xiāo)場(chǎng)景:
// 傳統(tǒng)硬編碼方式(噩夢(mèng)開(kāi)始...)
public BigDecimal calculateDiscount(Order order) {
BigDecimal discount = BigDecimal.ZERO;
if (order.getTotalAmount().compareTo(new BigDecimal("100")) >= 0) {
discount = discount.add(new BigDecimal("10"));
}
if (order.getUser().isVip()) {
discount = discount.add(new BigDecimal("5"));
}
// 更多if-else嵌套...
return discount;
}當(dāng)規(guī)則變成:"非VIP用戶(hù)滿(mǎn)200減30,VIP用戶(hù)滿(mǎn)150減40,且周二全場(chǎng)額外95折"時(shí),代碼將陷入維護(hù)地獄!
規(guī)則引擎通過(guò)分離規(guī)則邏輯解決這個(gè)問(wèn)題:
- 規(guī)則外置存儲(chǔ)(數(shù)據(jù)庫(kù)/文件)
- 支持動(dòng)態(tài)加載
- 聲明式規(guī)則語(yǔ)法
- 獨(dú)立執(zhí)行環(huán)境
下面給大家分享5種常用的規(guī)則引擎,希望對(duì)你會(huì)有所幫助。
1.五大常用規(guī)則引擎
1.1 Drools:企業(yè)級(jí)規(guī)則引擎扛把子
官網(wǎng):https://www.drools.org/
適用場(chǎng)景:
- 金融風(fēng)控規(guī)則(上百條復(fù)雜規(guī)則)
- 保險(xiǎn)理賠計(jì)算
- 電商促銷(xiāo)體系
實(shí)戰(zhàn):折扣規(guī)則配置
// 規(guī)則文件 discount.drl
rule "VIP用戶(hù)滿(mǎn)100減20"
when
$user: User(level == "VIP")
$order: Order(amount > 100)
then
$order.addDiscount(20);
endJava調(diào)用代碼:
KieServices kieServices = KieServices.Factory.get();
KieContainer kContainer = kieServices.getKieClasspathContainer();
KieSession kSession = kContainer.newKieSession("discountSession");
kSession.insert(user);
kSession.insert(order);
kSession.fireAllRules();優(yōu)點(diǎn):
- 完整的RETE算法實(shí)現(xiàn)
- 支持復(fù)雜的規(guī)則網(wǎng)絡(luò)
- 完善的監(jiān)控管理控制臺(tái)
缺點(diǎn):
- 學(xué)習(xí)曲線陡峭
- 內(nèi)存消耗較大
- 需要依賴(lài)Kie容器
適合:不差錢(qián)的大廠,規(guī)則復(fù)雜度高的場(chǎng)景
1.2 Easy Rules:輕量級(jí)規(guī)則引擎之王
官網(wǎng):https://github.com/j-easy/easy-rules
適用場(chǎng)景:
- 參數(shù)校驗(yàn)
- 簡(jiǎn)單風(fēng)控規(guī)則
- 審批流引擎
注解式開(kāi)發(fā):
@Rule(name = "雨天打折規(guī)則", description = "下雨天全場(chǎng)9折")
public class RainDiscountRule {
@Condition
public boolean when(@Fact("weather") String weather) {
return "rainy".equals(weather);
}
@Action
public void then(@Fact("order") Order order) {
order.setDiscount(0.9);
}
}引擎執(zhí)行:
RulesEngineParameters params = new RulesEngineParameters()
.skipOnFirstAppliedRule(true); // 匹配即停止
RulesEngine engine = new DefaultRulesEngine(params);
engine.fire(rules, facts);優(yōu)點(diǎn):
- 五分鐘上手
- 零第三方依賴(lài)
- 支持規(guī)則組合
缺點(diǎn):
- 不支持復(fù)雜規(guī)則鏈
- 缺少可視化界面
適合:中小項(xiàng)目快速落地,開(kāi)發(fā)人員不足時(shí)
1.3 QLExpress:阿里系腳本引擎之光
官網(wǎng):https://github.com/alibaba/QLExpress
適用場(chǎng)景:
- 動(dòng)態(tài)配置計(jì)算邏輯
- 財(cái)務(wù)公式計(jì)算
- 營(yíng)銷(xiāo)規(guī)則靈活變更
執(zhí)行動(dòng)態(tài)腳本:
ExpressRunner runner = new ExpressRunner();
DefaultContext<String, Object> context = new DefaultContext<>();
context.put("user", user);
context.put("order", order);
String express = "if (user.level == 'VIP') { order.discount = 0.85; }";
runner.execute(express, context, null, true, false);高級(jí)特性:
// 1. 函數(shù)擴(kuò)展
runner.addFunction("計(jì)算稅費(fèi)", new Operator() {
@Override
public Object execute(Object[] list) {
return (Double)list[0] * 0.06;
}
});
// 2. 宏定義
runner.addMacro("是否新用戶(hù)", "user.regDays < 30");優(yōu)點(diǎn):
- 腳本熱更新
- 語(yǔ)法接近Java
- 完善的沙箱安全
缺點(diǎn):
- 調(diào)試?yán)щy
- 復(fù)雜規(guī)則可讀性差
適合:需要頻繁修改規(guī)則的業(yè)務(wù)(如運(yùn)營(yíng)活動(dòng))
1.4 Aviator:高性能表達(dá)式專(zhuān)家
官網(wǎng):https://github.com/killme2008/aviatorscript
適用場(chǎng)景:
- 實(shí)時(shí)定價(jià)引擎
- 風(fēng)控指標(biāo)計(jì)算
- 大數(shù)據(jù)字段加工
性能對(duì)比(執(zhí)行10萬(wàn)次):
// Aviator 表達(dá)式
Expression exp = AviatorEvaluator.compile("user.age > 18 && order.amount > 100");
exp.execute(map);
// Groovy 腳本
new GroovyShell().evaluate("user.age > 18 && order.amount > 100");引擎 | 耗時(shí) |
Aviator | 220ms |
Groovy | 1850ms |
編譯優(yōu)化:
// 開(kāi)啟編譯緩存(默認(rèn)開(kāi)啟)
AviatorEvaluator.getInstance().useLRUExpressionCache(1000);
// 字節(jié)碼生成模式(JDK8+)
AviatorEvaluator.setOption(Options.ASM, true);優(yōu)點(diǎn):
- 性能碾壓同類(lèi)引擎
- 支持字節(jié)碼生成
- 輕量無(wú)依賴(lài)
缺點(diǎn):
- 只支持表達(dá)式
- 不支持流程控制
適合:對(duì)性能有極致要求的計(jì)算場(chǎng)景
1.5 LiteFlow:規(guī)則編排新物種
官網(wǎng):https://liteflow.com/
適用場(chǎng)景:
- 復(fù)雜業(yè)務(wù)流程
- 訂單狀態(tài)機(jī)
- 審核工作流
編排示例:
<chain name="orderProcess">
<then value="checkStock,checkCredit"/> <!-- 并行執(zhí)行 -->
<when value="isVipUser">
<then value="vipDiscount"/>
</when>
<otherwise>
<then value="normalDiscount"/>
</otherwise>
<then value="saveOrder"/>
</chain>Java調(diào)用:
LiteflowResponse response = FlowExecutor.execute2Resp("orderProcess", order, User.class);
if (response.isSuccess()) {
System.out.println("流程執(zhí)行成功");
} else {
System.out.println("失敗原因:" + response.getCause());
}優(yōu)點(diǎn):
- 可視化流程編排
- 支持異步、并行、條件分支
- 熱更新規(guī)則
缺點(diǎn):
- 新框架文檔較少
- 社區(qū)生態(tài)待完善
適合:需要靈活編排的復(fù)雜業(yè)務(wù)流
2.五大規(guī)則引擎橫向評(píng)測(cè)
圖片
性能壓測(cè)數(shù)據(jù)(單機(jī)1萬(wàn)次執(zhí)行):
引擎 | 耗時(shí) | 內(nèi)存占用 | 特點(diǎn) |
Drools | 420ms | 高 | 功能全面 |
Easy Rules | 38ms | 低 | 輕量易用 |
QLExpress | 65ms | 中 | 阿里系腳本引擎 |
Aviator | 28ms | 極低 | 高性能表達(dá)式 |
LiteFlow | 120ms | 中 | 流程編排專(zhuān)家 |
3.如何技術(shù)選型?
圖片
黃金法則:
- 簡(jiǎn)單場(chǎng)景:EasyRules + Aviator 組合拳
- 金融風(fēng)控:Drools 穩(wěn)如老狗
- 電商運(yùn)營(yíng):QLExpress 靈活應(yīng)變
- 工作流驅(qū)動(dòng):LiteFlow 未來(lái)可期
4.避坑指南
- Drools內(nèi)存溢出
// 設(shè)置無(wú)狀態(tài)會(huì)話(避免內(nèi)存積累)
KieSession session = kContainer.newStatelessKieSession();- QLExpress安全漏洞
// 禁用危險(xiǎn)方法
runner.addFunctionOfServiceMethod("exit", System.class, "exit", null, null);- 規(guī)則沖突檢測(cè)
// Drools沖突處理策略
KieSessionConfiguration config = KieServices.Factory.get().newKieSessionConfiguration();
config.setProperty("drools.sequential", "true"); // 按順序執(zhí)行總結(jié)
- 能用:替換if/else(新手村)
- 用好:規(guī)則熱更新+可視化(進(jìn)階)
- 用精:規(guī)則編排+性能優(yōu)化(大師級(jí))
曾有人問(wèn)我:“規(guī)則引擎會(huì)不會(huì)讓程序員失業(yè)?” 我的回答是:“工具永遠(yuǎn)淘汰不了思考者,只會(huì)淘汰手工作坊”。
真正的高手,不是寫(xiě)更多代碼,而是用更優(yōu)雅的方式解決問(wèn)題。





























