3. 规则语言入门:DRL(Drools Rule Language)语法基础

DRL(Drools Rule Language)是 Drools 规则引擎的原生规则语言,也是规则冲突检测与特征服务联动中最核心的编写载体。一个完整的 DRL 规则由三个部分组成:规则头(Rule Header)、条件部分(LHS,Left-Hand Side) 和 动作部分(RHS,Right-Hand Side)。理解这三者的结构、约束与协作方式,是后续进行规则冲突分析、特征编排和性能调优的前提。

3.1 规则头(Rule Header)

规则头定义了规则的元信息,包括规则名称、属性、优先级和分组等。它是规则引擎识别和执行规则的入口。

关键字 说明 示例
rule 声明规则开始,后跟规则名称 rule "检测高风险交易"
salience 设置规则优先级,数值越大越先执行 salience 100
no-loop 防止规则自身修改 Fact 导致无限循环 no-loop true
activation-group 同一组内只激活一条规则(互斥) activation-group "risk-level"
agenda-group 将规则分组到议程,控制执行焦点 agenda-group "feature-eval"
when 标记条件部分开始 when
then 标记动作部分开始 then
end 标记规则结束 end
实践建议:在特征服务联动场景中,salience 和 activation-group 是控制规则冲突与特征计算顺序的关键属性。建议为每个规则显式设置 no-loop true,避免因特征值更新导致规则重复触发。

3.2 条件部分(LHS)

LHS 是规则的条件匹配区域,使用 when 关键字引导。引擎会在此处对工作内存中的 Fact 对象进行模式匹配。LHS 支持多种约束语法,包括字段比较、逻辑组合、存在性检查等。

3.2.1 基本模式与字段约束

rule "检查交易金额超限"
  when
    $t : Transaction( amount > 10000, currency == "CNY" )
  then
    // RHS 动作
end

上述规则中:

  • $t 是绑定变量,可在 RHS 中引用该 Fact 对象。
  • Transaction 是 Fact 类型。
  • amount > 10000 和 currency == "CNY" 是字段约束,支持 >、<、==、!=、matches、contains 等操作符。

3.2.2 多条件组合与逻辑操作符

rule "组合条件:高风险设备 + 异常时段"
  when
    $d : Device( riskScore >= 80 )
    $t : Transaction( deviceId == $d.id, hourOfDay < 6 || hourOfDay > 23 )
  then
    // 触发联动动作
end

LHS 支持 &&(与)、||(或)、!(非)以及括号分组。多个 Fact 模式之间默认是 && 关系,所有模式必须同时匹配。

3.2.3 存在性与集合约束

关键字 用途 示例
exists 检查是否存在至少一个匹配 exists Alert( severity == "HIGH" )
not 检查不存在任何匹配 not Blacklist( ip == $t.clientIp )
forall 检查所有对象都满足条件 forall( Feature( status == "READY" ) )
collect 收集匹配对象到集合 List from collect( Feature( name.startsWith("risk_") ) )
常见陷阱:exists 和 not 在规则冲突检测中容易导致意外的激活/失活。例如,not Blacklist(...) 会在黑名单 Fact 被插入或删除时重新评估,可能引发连锁冲突。建议在关键规则上使用 activation-group 进行隔离。

3.3 动作部分(RHS)

RHS 是规则触发后执行的动作区域,使用 then 关键字引导。RHS 中可以编写 Java 代码、调用服务、更新 Fact、插入新 Fact 或触发其他规则。

3.3.1 常用 RHS 操作

rule "特征联动:更新风险评分"
  when
    $t : Transaction( amount > 50000 )
    $f : Feature( transactionId == $t.id, name == "risk_score" )
  then
    // 更新特征值
    modify( $f ) {
      setValue( $f.getValue() + 20 ),
      setUpdatedTime( new java.util.Date() )
    }

    // 插入告警 Fact
    Alert alert = new Alert();
    alert.setType("HIGH_RISK");
    alert.setMessage("大额交易风险提升");
    insert( alert );

    // 调用外部特征服务
    FeatureServiceClient.updateFeature($t.getId(), "risk_level", "HIGH");
end

3.3.2 RHS 中的关键方法与宏

方法/宏 作用 冲突影响
modify( $fact ) { ... } 更新 Fact 属性并通知引擎 可能重新激活其他规则
update( $fact ) 更新 Fact 并重新评估 高冲突风险,慎用
insert( newFact ) 插入新 Fact 到工作内存 可能触发新规则链
retract( $fact ) 从工作内存移除 Fact 可能导致规则失活
drools.halt() 立即停止规则执行 中断当前议程
特征服务联动要点:在 RHS 中调用外部特征服务时,建议使用异步回调或批量更新接口,避免在规则执行线程中阻塞。同时,modify 操作会触发规则引擎的重新评估,务必配合 no-loop 和 activation-group 防止冲突风暴。

3.4 DRL 规则结构总览

以下 SVG 图展示了 DRL 规则的完整结构,以及规则头、LHS、RHS 之间的数据流与执行关系。

DRL 规则结构总览 规则头(Rule Header) rule "规则名称" salience / no-loop activation-group / agenda-group when 条件部分(LHS) Fact 模式匹配 字段约束 / 逻辑组合 exists / not / collect then 动作部分 (RHS) modify insert / retract 规则执行流与冲突触发点 ① 规则头决定优先级与分组 → ② LHS 匹配 Fact 模式 → ③ RHS 执行动作 ④ modify/insert 可能重新激活 LHS 匹配 → ⑤ 产生规则冲突 冲突检测点:salience 排序、activation-group 互斥、no-loop 防循环 反馈循环(冲突源)

3.5 完整 DRL 规则示例

以下是一个结合特征服务联动的完整 DRL 规则,展示了规则头、LHS 和 RHS 的协同工作:

package com.risk.feature.rules

import com.risk.model.Transaction
import com.risk.model.Feature
import com.risk.model.Alert
import com.risk.service.FeatureServiceClient

rule "特征联动:设备指纹异常检测"
  salience 200
  no-loop true
  activation-group "device-risk"
  when
    // 条件1:交易金额超过阈值
    $t : Transaction( amount > 20000, status == "PENDING" )

    // 条件2:设备指纹特征异常(风险分 > 70 或 新设备标记)
    $f : Feature( transactionId == $t.id, 
                  (name == "device_risk_score" && doubleValue > 70) ||
                  (name == "is_new_device" && stringValue == "true") )

    // 条件3:该设备在过去1小时内没有触发过同类告警(防重复)
    not Alert( deviceId == $t.deviceId, type == "DEVICE_ANOMALY", 
               timestamp > ($t.timestamp - 3600000) )
  then
    // 动作1:更新特征值
    modify( $f ) {
      setDoubleValue( $f.getDoubleValue() + 15 ),
      setUpdatedTime( new java.util.Date() )
    }

    // 动作2:插入告警
    Alert alert = new Alert();
    alert.setType("DEVICE_ANOMALY");
    alert.setDeviceId($t.getDeviceId());
    alert.setTransactionId($t.getId());
    alert.setTimestamp(new java.util.Date());
    insert( alert );

    // 动作3:调用外部特征服务,同步更新特征库
    FeatureServiceClient.updateFeature(
      $t.getId(), 
      "device_anomaly_flag", 
      "true"
    );

    // 动作4:日志记录(生产环境建议使用 Logger)
    System.out.println("设备异常检测触发: " + $t.getId());
end
学习路径提示:掌握 DRL 语法后,下一步应重点理解规则冲突的触发机制——特别是 modify 和 insert 如何导致 LHS 重新评估。这是第 4 章“规则冲突检测原理”的核心内容。