3. 风控网关架构详解:请求路由、规则引擎、模型调用、限流熔断等核心组件
风控网关是整个实时风控系统的流量入口与决策中枢。它不仅要承接每秒数万笔的线上请求,还要在毫秒级内完成路由分发、规则匹配、模型推理与流量治理。本章从架构视角拆解风控网关的四大核心组件,并结合特征服务与回放场景,说明每个组件的设计要点与常见陷阱。
3.1 风控网关整体架构分层
一个生产级风控网关通常分为四层:接入层、路由层、决策层与治理层。各层职责清晰,通过异步管道串联,确保高吞吐与低延迟。
架构分层速览
| 层级 | 核心组件 | 关键指标 | 回放关注点 |
|---|---|---|---|
| 接入层 | 协议适配、请求解析、参数校验 | QPS、P99 延迟 | 请求体完整性校验 |
| 路由层 | 请求路由、策略分发、上下文构建 | 路由命中率、分片均衡 | 路由 Key 一致性 |
| 决策层 | 规则引擎、模型调用、特征聚合 | 规则执行耗时、模型 RT | 特征版本对齐 |
| 治理层 | 限流熔断、降级、监控、审计 | 熔断次数、降级率 | 限流阈值回放 |
3.2 请求路由:流量分发与上下文构建
请求路由是网关的第一道逻辑关卡。它根据请求中的业务标识(如用户ID、设备ID、订单ID)将流量分发到对应的策略集与特征管道。
3.2.1 路由策略设计
- 一致性哈希路由:按用户ID哈希分片,保证同一用户请求始终路由到同一决策节点,避免特征缓存失效。
- 策略版本路由:根据请求中的策略版本号或AB实验标识,将流量导向不同版本的规则集与模型。
- 灰度路由:按比例或白名单将部分请求路由到新版本策略,用于线上验证与回放对比。
回放避坑:回放时必须保证路由 Key 与线上完全一致。常见偏差包括:路由 Key 为空、哈希算法不一致、分片数变更导致路由结果漂移。
3.2.2 上下文构建
路由完成后,网关会构建一个请求上下文(Request Context),包含原始请求、解析后的参数、预加载的特征快照以及链路追踪 ID。上下文贯穿整个决策流程,是回放时比对输入一致性的核心对象。
// 请求上下文结构示例
public class RiskContext {
private String requestId; // 全局唯一ID
private String routeKey; // 路由Key(如userId)
private Map<String, Object> rawParams; // 原始请求参数
private Map<String, Feature> preFeatures; // 预加载特征
private String strategyVersion; // 策略版本号
private long timestamp; // 请求到达时间
// ... 其他元数据
}
3.3 规则引擎:条件匹配与决策树
规则引擎是风控决策的核心执行单元。它接收上下文中的特征数据,按照预定义的规则集进行条件匹配,输出命中结果与风险等级。
3.3.1 规则引擎执行流程
- 规则加载:从配置中心拉取最新规则集,编译为可执行对象(如 DAG 或决策树)。
- 特征注入:将上下文中的特征注入规则上下文,供条件表达式引用。
- 条件匹配:按优先级依次执行规则,支持与/或/非逻辑组合。
- 动作输出:命中规则后输出动作(如拒绝、人工审核、放行)并记录命中日志。
3.3.2 规则引擎对比:传统 vs 现代
| 维度 | 传统规则引擎(Drools) | 现代轻量引擎(自研/表达式引擎) |
|---|---|---|
| 执行模式 | RETE 网络,全量匹配 | 短路匹配,按优先级截断 |
| 延迟 | 1-5ms(规则多时更高) | 0.1-0.5ms |
| 热更新 | 需重新编译 | 支持动态加载 |
| 回放友好度 | 规则版本需快照 | 天然支持版本化 |
回放陷阱:规则引擎的短路逻辑可能导致回放结果不一致。例如线上规则 A 命中后直接返回,但回放时规则 A 因特征缺失未命中,继续执行规则 B 产生不同结果。回放时必须记录规则命中路径。
3.4 模型调用:特征拼接与推理服务
风控网关需要调用多个模型(如评分卡、XGBoost、深度学习模型)进行风险评分。模型调用环节是延迟消耗最大的部分,也是回放对比中最容易出问题的环节。
3.4.1 模型调用架构
- 特征拼接:从上下文中提取模型所需的特征向量,进行缺失值填充与标准化。
- 模型路由:根据模型 ID 或版本号,将请求转发到对应的推理服务(如 TensorFlow Serving、ONNX Runtime)。
- 结果聚合:多个模型返回的分数按权重组合,生成最终风险评分。
// 模型调用伪代码
public ModelResult callModel(RiskContext ctx, String modelId) {
// 1. 特征拼接
FeatureVector vector = featureService.buildVector(ctx, modelId);
// 2. 调用推理服务
InferenceResponse response = inferenceClient.predict(modelId, vector);
// 3. 记录调用日志(用于回放)
auditLogger.logModelCall(ctx.getRequestId(), modelId, vector, response);
return response.toModelResult();
}
3.4.2 模型版本对齐
回放时最大的挑战是模型版本一致性。线上模型可能已迭代多次,而回放数据使用的是旧版本特征与模型。解决方案是在回放请求中携带模型版本号,强制使用与线上一致的模型版本。
模型回放检查清单
- 特征拼接逻辑是否与线上一致(包括缺失值处理)
- 模型版本是否锁定(避免回放时调用最新模型)
- 推理服务超时设置是否与线上一致(超时可能导致降级)
- 模型结果是否包含置信度与特征贡献度(用于偏差分析)
3.5 限流熔断:流量治理与自我保护
限流与熔断是网关的自我保护机制。当流量超过系统阈值或下游服务异常时,网关主动丢弃或降级请求,防止雪崩。
3.5.1 限流策略
| 策略 | 原理 | 适用场景 | 回放影响 |
|---|---|---|---|
| 令牌桶 | 固定速率生成令牌,请求消耗令牌 | 平滑限流 | 回放时需关闭限流或使用独立配额 |
| 漏桶 | 固定速率处理请求,超出则排队或丢弃 | 保护下游 | 回放请求可能被排队,影响延迟对比 |
| 滑动窗口 | 统计时间窗口内请求数,超过阈值则拒绝 | 突发流量控制 | 窗口边界可能导致回放结果不一致 |
3.5.2 熔断机制
熔断器监控下游服务(如特征服务、模型服务)的错误率与延迟。当错误率超过阈值时,熔断器打开,后续请求直接降级返回默认值,避免等待超时。
回放建议:回放时应禁用限流与熔断,或使用独立的回放集群。否则回放请求可能被限流丢弃,导致回放覆盖率不足。同时,熔断降级后的默认值应与线上降级逻辑一致,否则回放结果无法反映真实决策。
3.6 核心组件回放对比要点总结
将上述四个核心组件的回放对比要点汇总如下,便于在实际项目中对照检查。
| 组件 | 回放对比维度 | 常见偏差原因 | 解决方案 |
|---|---|---|---|
| 请求路由 | 路由 Key、分片结果 | 哈希算法不一致、分片数变更 | 锁定路由算法版本 |
| 规则引擎 | 规则版本、命中路径 | 规则热更新、短路逻辑 | 记录规则版本与命中顺序 |
| 模型调用 | 特征向量、模型版本 | 特征缺失、模型迭代 | 锁定模型版本,快照特征 |
| 限流熔断 | 限流阈值、熔断状态 | 回放流量被限流、熔断降级 | 回放集群独立,禁用治理 |
核心原则:回放对比的目标不是让回放结果与线上完全一致,而是可解释地发现偏差。每个组件的版本、输入、输出都应被记录,偏差发生时能快速定位到具体环节。