4. 评分引擎核心设计:定义评分规则引擎接口、策略模式实现可插拔规则、规则优先级与权重配置、评分结果数据结构设计
评分引擎是整个低延迟接口的计算核心。本章将围绕“可扩展、可配置、高性能”三个目标,设计一套支持策略模式、优先级调度与权重聚合的评分规则引擎。我们从接口定义开始,逐步构建完整的评分骨架。
4.1 评分规则引擎接口定义
引擎接口是评分系统的契约。所有评分规则必须实现该接口,保证引擎能够统一调用。接口设计遵循单一职责原则,只暴露评分计算与元数据获取两个核心方法。
| 方法签名 | 返回值 | 说明 |
|---|---|---|
evaluate(context: ScoreContext): ScoreResult |
ScoreResult |
执行评分逻辑,返回单项评分结果 |
getRuleMeta(): RuleMeta |
RuleMeta |
返回规则元数据(名称、优先级、权重等) |
isApplicable(context: ScoreContext): boolean |
boolean |
判断当前上下文是否适用该规则 |
// 评分规则引擎核心接口
public interface ScoringRule {
ScoreResult evaluate(ScoreContext context);
RuleMeta getRuleMeta();
boolean isApplicable(ScoreContext context);
}
// 规则元数据
public class RuleMeta {
private String ruleId; // 规则唯一标识
private String name; // 规则名称
private int priority; // 优先级(数值越小优先级越高)
private double weight; // 权重(0.0 ~ 1.0)
private String description; // 规则描述
// getters & setters ...
}
// 评分上下文
public class ScoreContext {
private String userId;
private String targetId;
private Map<String, Object> attributes; // 扩展属性
// getters & setters ...
}
设计要点:接口中的
isApplicable 方法允许引擎在运行时动态过滤规则,避免无效计算。这是低延迟优化的第一道关卡。
4.2 策略模式实现可插拔规则
策略模式让评分规则可以独立变化、自由组合。每个规则是一个策略,引擎作为上下文持有策略集合,运行时按需调度。新增规则时只需添加新实现类,无需修改引擎代码。
// 引擎核心实现
public class ScoreEngine {
private List<ScoringRule> rules;
public ScoreEngine(List<ScoringRule> rules) {
// 按优先级排序
this.rules = rules.stream()
.sorted(Comparator.comparingInt(r -> r.getRuleMeta().getPriority()))
.collect(Collectors.toList());
}
public ScoreResult evaluate(ScoreContext context) {
List<ScoreResult> results = new ArrayList<>();
for (ScoringRule rule : rules) {
if (rule.isApplicable(context)) {
long start = System.nanoTime();
ScoreResult result = rule.evaluate(context);
result.setElapsedNanos(System.nanoTime() - start);
results.add(result);
}
}
return ScoreAggregator.aggregate(results);
}
}
4.3 规则优先级与权重配置
优先级决定规则执行顺序,权重决定最终分数的贡献比例。两者共同构成评分引擎的调度与聚合策略。
4.3.1 优先级调度策略
- 数值越小优先级越高:优先级 1 的规则先于优先级 10 执行。
- 短路机制:高优先级规则返回致命分数(如 0 分)时,可跳过后续规则。
- 分组执行:相同优先级的规则可并行执行,提升吞吐量。
4.3.2 权重配置示例
| 规则名称 | 优先级 | 权重 | 说明 |
|---|---|---|---|
| ContentQualityRule | 1 | 0.40 | 内容质量权重最高 |
| UserActivityRule | 2 | 0.25 | 用户活跃度次之 |
| TimelinessRule | 3 | 0.20 | 时效性 |
| ReputationRule | 4 | 0.15 | 信誉评分 |
// 权重聚合器实现
public class ScoreAggregator {
public static ScoreResult aggregate(List<ScoreResult> results) {
double totalScore = 0.0;
double totalWeight = 0.0;
Map<String, Object> details = new LinkedHashMap<>();
for (ScoreResult result : results) {
double weight = result.getWeight();
totalScore += result.getScore() * weight;
totalWeight += weight;
details.put(result.getRuleId(), result.getScore());
}
// 归一化处理
double finalScore = totalWeight > 0 ? totalScore / totalWeight : 0.0;
return new ScoreResult(finalScore, details);
}
}
性能优化提示:权重配置建议从外部配置中心(如 Apollo、Nacos)动态加载,避免硬编码。引擎启动时一次性加载规则列表,运行时只做计算,不做反射或动态编译。
4.4 评分结果数据结构设计
评分结果需要同时满足“快速序列化”和“丰富信息”两个要求。我们设计两级结构:顶层为总分,底层为规则明细。
// 评分结果实体
public class ScoreResult {
private double totalScore; // 最终总分
private Map<String, RuleDetail> ruleDetails; // 规则明细
private long elapsedNanos; // 引擎总耗时(纳秒)
private String status; // SUCCESS / PARTIAL / FAILED
// 内部明细类
public static class RuleDetail {
private double score;
private double weight;
private long elapsedNanos;
// getters & setters ...
}
}
// JSON 序列化示例(只返回总分)
// { "totalScore": 87.5, "status": "SUCCESS", "elapsedMs": 1.2 }
// 完整返回示例
// {
// "totalScore": 87.5,
// "status": "SUCCESS",
// "elapsedMs": 1.2,
// "ruleDetails": {
// "contentQuality": { "score": 90.0, "weight": 0.4, "elapsedMs": 0.3 },
// "userActivity": { "score": 85.0, "weight": 0.25, "elapsedMs": 0.2 },
// "timeliness": { "score": 80.0, "weight": 0.2, "elapsedMs": 0.4 },
// "reputation": { "score": 95.0, "weight": 0.15, "elapsedMs": 0.1 }
// }
// }
序列化优化:对于低延迟场景,建议在 API 层提供
?detail=false 参数,默认只返回总分和状态,减少 JSON 体积和序列化时间。ruleDetails 仅在调试或审计时启用。
4.5 本章小结
- 接口设计:
ScoringRule接口定义了评分、元数据、适用性三个核心方法,保证引擎与规则解耦。 - 策略模式:每个规则独立实现,引擎通过组合方式调度,新增规则零侵入。
- 优先级与权重:优先级控制执行顺序,权重控制分数贡献,两者配合实现灵活评分策略。
- 结果结构:
ScoreResult包含总分、明细、耗时、状态,支持按需序列化,兼顾信息完整性与传输效率。