4. 规则引擎基础:规则的定义、规则表达式、优先级与冲突处理

规则引擎是灰度切换系统的决策核心。它将“在什么条件下,对哪些流量执行什么操作”这一业务逻辑,从硬编码中剥离出来,形成可配置、可测试、可回测的独立模块。本章将拆解规则引擎的四个基础构件:规则定义、规则表达式、优先级与冲突处理。

4.1 规则的定义:原子单元

一条规则是最小的决策单元,通常包含三个核心要素:

要素 说明 示例
条件(Condition) 触发规则执行的布尔表达式 user.city == '北京' AND order.amount > 100
动作(Action) 条件满足时执行的操作 SET routing = 'new_engine_v2'
元数据(Metadata) 规则的标识、版本、描述、生效时间等 rule_id: R004, version: 2, status: active
实践建议: 在灰度切换场景中,建议为每条规则分配全局唯一的 rule_id,并在元数据中记录创建人和变更日志,便于回测追溯。

4.2 规则表达式:条件构建语法

规则表达式决定了条件的灵活性与表达能力。常见的表达式类型包括:

  • 比较表达式: field operator value,如 user.age >= 18、city IN ('北京', '上海')。
  • 逻辑组合表达式: 使用 AND、OR、NOT 连接多个条件,如 (region = '华东') AND (vip_level > 3)。
  • 函数表达式: 调用内置函数处理数据,如 hash(user_id) % 100 < 5(按用户ID哈希取模做灰度比例)。
  • 正则表达式: 用于模式匹配,如 email MATCHES '.*@company\.com'。
SQL回测场景: 规则表达式应支持与SQL WHERE子句类似的语义,以便在回测阶段直接映射到SQL查询条件,实现“一次编写,双重验证”。

4.3 规则优先级:决策顺序

当多条规则的条件同时满足时,优先级决定了哪条规则最终生效。常见的优先级策略有:

策略 描述 适用场景
数字优先级 为每条规则分配一个整数(1为最高),数值越小优先级越高 通用场景,灵活可控
精确匹配优先 条件更具体的规则优先于条件宽泛的规则 白名单/黑名单场景
最近优先 最后更新的规则优先 快速热修复场景
权重轮询 按权重比例分配命中概率 A/B测试流量分配
避坑提示: 避免使用“创建时间”作为唯一优先级依据,因为规则迁移或重新加载时可能导致顺序错乱。推荐显式声明 priority 字段。

4.4 冲突处理:决策收敛

冲突发生在多条规则条件同时满足,且动作互斥时。例如:规则A要求路由到新引擎,规则B要求路由到旧引擎。冲突处理机制确保引擎能收敛到唯一结果。

常见的冲突处理模式:

  • 优先级裁决: 直接选择优先级最高的规则动作,忽略其他规则。
  • 动作合并: 如果动作是叠加的(如添加标签),则合并所有动作结果。
  • 阻断机制: 一旦命中高优先级规则,立即停止后续规则评估(短路模式)。
  • 冲突日志: 记录所有冲突的规则对,供人工审计。

下图展示了规则引擎从条件匹配到冲突解决的核心流程:

规则引擎决策流程 输入事件/请求 规则匹配(条件评估) 命中? 默认规则 多条命中 冲突处理 输出决策结果 说明 未命中时走默认规则 命中多条时进入冲突处理

4.5 规则冲突矩阵:可视化决策边界

当规则数量增长到数十条时,人工推理冲突变得困难。冲突矩阵是一种有效的可视化工具,用于识别规则之间的互斥关系。

下图展示了一个简化的冲突矩阵示例,其中 X 表示两条规则存在冲突:

规则冲突矩阵(示例) 规则 R1 R2 R3 R4 R1 R2 R3 R4 X ✓ X X ✓ X 冲突 无冲突 自身 通过矩阵可快速定位需要人工仲裁的规则对

4.6 规则定义与冲突处理的代码示例

以下是一个简化的规则引擎核心代码片段,展示了规则定义、优先级排序和冲突检测的逻辑:

// 规则定义结构
public class Rule {
    private String ruleId;
    private int priority;          // 数值越小优先级越高
    private String conditionExpr;  // 条件表达式
    private String action;         // 动作指令
    private long version;
    
    // 评估条件是否满足
    public boolean evaluate(Map<String, Object> context) {
        // 调用表达式引擎解析 conditionExpr
        return ExpressionEngine.evaluate(conditionExpr, context);
    }
}

// 规则引擎核心
public class RuleEngine {
    private List<Rule> rules;  // 按优先级排序
    
    public DecisionResult execute(Map<String, Object> context) {
        List<Rule> matchedRules = new ArrayList<>();
        
        // 1. 条件匹配
        for (Rule rule : rules) {
            if (rule.evaluate(context)) {
                matchedRules.add(rule);
            }
        }
        
        // 2. 冲突检测
        if (matchedRules.isEmpty()) {
            return DecisionResult.defaultResult();
        } else if (matchedRules.size() == 1) {
            return DecisionResult.of(matchedRules.get(0));
        } else {
            // 3. 冲突处理:优先级裁决 + 日志记录
            Rule winner = matchedRules.get(0); // 已按优先级排序
            logConflict(matchedRules, winner);
            return DecisionResult.of(winner);
        }
    }
}
回测对齐: 在SQL回测阶段,规则引擎的 conditionExpr 应能直接翻译为 WHERE 子句,action 映射为 SELECT 或 CASE WHEN 分支,从而实现规则逻辑与回测SQL的语义等价。