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 表示两条规则存在冲突:
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的语义等价。