2. 在线推理链路整体架构:请求入口、特征工程、模型推理、结果后处理、响应返回的全链路设计
在线推理链路是信用评分模型从接收到实时请求到返回评分结果的完整执行路径。与离线批量评分不同,在线推理对延迟、稳定性和可观测性有极高要求。本章将逐层拆解全链路的核心环节,并给出各阶段的设计要点与常见陷阱。
核心原则:在线推理链路必须满足 P99 延迟 < 200ms、可用性 > 99.95%、数据一致性最终可达。任何环节的阻塞或异常都可能导致用户拒贷或资金损失。
2.1 全链路阶段划分
一条标准的信用评分在线推理链路包含以下 5 个阶段,每个阶段都有明确的输入、输出和职责边界:
| 阶段 | 输入 | 输出 | 核心职责 | 典型耗时占比 |
|---|---|---|---|---|
| 请求入口 | HTTP/gRPC 原始请求 | 标准化请求上下文 | 协议解析、鉴权、限流、参数校验 | 5% |
| 特征工程 | 原始字段 + 外部数据 | 特征向量 (Dense/Sparse) | 缺失填充、分箱编码、交叉特征、实时聚合 | 40% |
| 模型推理 | 特征向量 | 原始分数 / 概率 | 模型加载、前向计算、GPU/CPU 调度 | 30% |
| 结果后处理 | 原始分数 | 校准评分 + 拒绝码 | 分数映射、策略拦截、可解释性输出 | 15% |
| 响应返回 | 最终结果 | HTTP/gRPC 响应 | 序列化、日志埋点、异步审计 | 10% |
设计提示:特征工程通常是最耗时的环节,尤其是涉及实时聚合(如近 30 天逾期次数)或外部数据源(如征信查询)时。建议对特征计算做 预计算 + 缓存 分层,避免每次请求都重复计算静态特征。
2.2 全链路架构总览
下图展示了在线推理链路的完整数据流与组件关系。请求从左侧进入,经过网关、特征服务、模型服务、后处理服务,最终返回给调用方。每个服务内部都有独立的超时、熔断和监控机制。
2.3 各阶段详细设计
2.3.1 请求入口
请求入口是链路的第一个关卡,负责将外部请求转化为内部标准格式。常见实现方式包括 Nginx + Lua、Kong 网关或自研 gRPC 代理。
- 协议适配:支持 HTTP/1.1、HTTP/2、gRPC,内部统一使用 Protobuf 序列化。
- 鉴权与限流:基于 Token 或 HMAC 签名验证身份;使用令牌桶或滑动窗口限流,防止突发流量冲垮下游。
- 参数校验:检查必填字段(如身份证号、手机号)是否为空,格式是否合法(如手机号 11 位数字)。
- 请求去重:基于请求 ID(UUID)做幂等校验,防止重复提交导致重复扣分。
常见陷阱:请求入口层容易忽略 超时传播。如果上游设置了 500ms 超时,但入口层内部又设置了 800ms 超时,会导致上游超时后请求仍在处理,浪费计算资源。建议入口层超时时间 = 上游超时 × 0.8。
2.3.2 特征工程
特征工程是在线推理中最复杂、最容易出错的环节。它需要将原始数据转化为模型可接受的数值向量,同时保证计算效率。
特征工程通常分为三类操作:
| 特征类型 | 示例 | 计算方式 | 缓存策略 |
|---|---|---|---|
| 基础特征 | 年龄、性别、收入 | 直接从请求字段提取 | 无需缓存 |
| 聚合特征 | 近 30 天逾期次数 | 实时查询数据库或流计算 | Redis 缓存,TTL 5min |
| 外部特征 | 征信查询次数 | 调用第三方 API | 本地缓存,TTL 1h |
特征工程的核心代码示例(Python 伪代码):
def feature_pipeline(request: ScoringRequest) -> FeatureVector:
# 1. 基础特征提取
base_features = extract_base_features(request)
# 2. 聚合特征(带缓存)
agg_key = f"agg:{request.user_id}"
agg_features = cache.get(agg_key)
if agg_features is None:
agg_features = compute_aggregation(request.user_id)
cache.set(agg_key, agg_features, ttl=300)
# 3. 外部特征(带熔断)
ext_features = {}
try:
ext_features = call_external_api(request.id_card, timeout=0.05)
except TimeoutError:
ext_features = {"external_risk": -1} # 默认值
# 4. 特征编码与拼接
feature_vector = encode_and_concat(base_features, agg_features, ext_features)
return feature_vector
2.3.3 模型推理
模型推理阶段负责加载训练好的模型文件,对特征向量进行前向计算,输出原始分数或概率。常见的模型类型包括逻辑回归、XGBoost、LightGBM 和深度神经网络。
- 模型加载:使用 ONNX Runtime、TensorFlow Serving 或自研推理引擎。模型文件应预热加载,避免冷启动延迟。
- 批处理:支持动态批处理(dynamic batching),将多个请求合并为一个批次推理,提高 GPU 利用率。
- 版本管理:模型版本通过配置中心下发,支持 A/B 测试和灰度发布。
- 降级策略:当模型推理失败时,回退到备用模型(如简单逻辑回归)或返回默认分数。
性能优化:对于 XGBoost 模型,使用
predict() 而非 predict_proba() 可减少 30% 推理时间;对于 DNN 模型,使用 FP16 精度推理可提升 2 倍吞吐量。
2.3.4 结果后处理
模型输出的原始分数(如 0.85)需要经过后处理才能转化为业务可用的信用评分(如 650 分)。后处理阶段还负责策略拦截和可解释性输出。
| 后处理步骤 | 输入 | 输出 | 说明 |
|---|---|---|---|
| 分数映射 | 原始概率 [0,1] | 信用评分 [300,850] | 使用分段线性映射或逻辑映射 |
| 策略拦截 | 评分 + 原始特征 | 拒绝码 / 通过 | 命中黑名单、多头超限等直接拒绝 |
| 可解释性 | 特征贡献度 | SHAP 值 / 特征排名 | 返回 Top-3 拒绝原因 |
| 分数校准 | 原始分数 | 校准后分数 | Platt 缩放或 Isotonic 回归 |
2.3.5 响应返回
响应返回是链路的最后一环,负责将最终结果序列化并返回给调用方。同时,该阶段需要完成日志记录和异步审计。
- 序列化:使用 Protobuf 或 JSON 格式,推荐 Protobuf 以减少带宽和序列化时间。
- 日志埋点:记录全链路 Trace ID、每个阶段的耗时、特征哈希值(脱敏)、模型版本、最终评分。
- 异步审计:将请求和响应原始数据写入消息队列(Kafka),供离线分析和模型监控使用。
- 错误码规范:定义统一的错误码枚举,如
SUCCESS=0、PARAM_ERROR=1001、MODEL_TIMEOUT=2001。
2.4 全链路时序与超时控制
在线推理对延迟极其敏感,必须为每个阶段设置独立的超时时间,并实现全链路超时传播。下图展示了典型的时序控制策略:
2.5 全链路可观测性设计
可观测性是在线推理链路稳定运行的基石。每个阶段都需要暴露关键指标,以便快速定位瓶颈和异常。
| 指标类别 | 具体指标 | 采集方式 | 告警阈值 |
|---|---|---|---|
| 延迟 | P50 / P99 / P999 延迟 | Prometheus Histogram | P99 > 200ms 告警 |
| 吞吐量 | QPS / TPS | Prometheus Counter | QPS 突降 50% 告警 |
| 错误率 | HTTP 5xx / 超时 / 特征缺失 | Prometheus Counter | 错误率 > 1% 告警 |
| 资源 | CPU / 内存 / GPU 利用率 | Node Exporter + DCGM | CPU > 80% 或 GPU > 90% 告警 |
| 业务 | 平均评分 / 拒绝率 / 通过率 | 业务日志聚合 | 拒绝率突增 20% 告警 |
最佳实践:使用 OpenTelemetry 实现全链路 Trace,每个阶段注入相同的 Trace ID。当请求超时或失败时,可以通过 Trace ID 快速查询每个阶段的耗时和错误信息,将排查时间从小时级缩短到分钟级。