4. 全链路监控架构

4.1 三大支柱的分工与边界

在AI DevOps场景中,全链路监控并非单一工具能覆盖,而是由分布式追踪(Tracing)、指标收集(Metrics)、日志聚合(Logging)三大支柱协同构成。三者分别回答不同维度的问题:追踪回答“一次请求经历了哪些服务、每步耗时多少”;指标回答“系统当前吞吐量、错误率、资源水位如何”;日志回答“某个具体错误发生时,上下文细节是什么”。

三者数据形态差异显著:追踪数据是树状结构(一条Trace由多个Span组成),指标数据是时序数值(按时间戳聚合的计数器或直方图),日志数据是非结构化文本(但可解析为字段)。架构设计的第一原则是分通道采集、统一存储查询——避免将所有数据灌入同一存储导致性能瓶颈,同时通过关联标识(Trace ID / Request ID)在查询层打通三者。

核心关联机制:在入口网关生成全局唯一的 trace_id,通过HTTP Header(如 X-Request-ID)向下游传递。日志采集器自动将 trace_id 注入日志字段;指标系统在聚合时保留 service.name 和 trace_id 的映射索引。这样,当用户反馈“订单支付失败”时,可先按 trace_id 找到完整调用链,再过滤该链路内所有服务日志,同时查看该时段各节点错误率指标。
用户请求入口 API 网关(生成 trace_id) 服务A:订单服务 Span: /api/order 服务B:支付服务 Span: /api/pay 服务C:库存服务 Span: /api/stock HTTP调用 HTTP调用 ① 分布式追踪(Tracing) • 采集器:Jaeger / Zipkin Agent • 数据模型:Trace → Span 树 • 存储:Elasticsearch / Cassandra • 关键字段:trace_id, span_id, parent_span_id, duration ② 指标收集(Metrics) • 采集器:Prometheus Exporter • 数据模型:时序数值 + 标签 • 存储:Prometheus TSDB / Thanos • 关键指标:QPS, P99延迟, 错误率, CPU/内存水位 ③ 日志聚合(Logging) • 采集器:Filebeat / Fluentd • 数据模型:JSON结构化文本 • 存储:Elasticsearch + S3冷备 • 关键字段:timestamp, level, service, trace_id, message

4.2 分布式追踪的架构设计

追踪系统的核心是埋点规范与采样策略。在AI服务中,一次模型推理可能涉及特征服务、模型服务、结果后处理等多个Span,若全量采集会产生巨大开销。生产环境通常采用头采样(Head-based Sampling)与尾采样(Tail-based Sampling)结合:入口处按10%比例采样,对错误链路(HTTP 5xx、超时)强制全采,对高价值业务(支付、模型训练任务)按100%采集。

架构上,各服务通过SDK或Agent将Span上报到Collector,Collector负责校验、清洗、路由,最终写入存储。关键设计点是Span的传播上下文——在异步消息(Kafka)场景下,需将 trace_id 写入消息头,消费者侧再恢复上下文,否则跨异步边界追踪会断裂。

// 典型Span结构(OpenTelemetry格式)
{
  "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
  "span_id": "a2fb4a1d1a96d312",
  "parent_span_id": "f5f5d5b5a5c5b5a5",
  "name": "POST /api/v1/predict",
  "kind": "SPAN_KIND_SERVER",
  "start_time": "2025-03-15T10:00:00.123Z",
  "end_time": "2025-03-15T10:00:00.456Z",
  "attributes": {
    "http.method": "POST",
    "http.status_code": 200,
    "model.name": "resnet50",
    "batch.size": 32
  }
}

4.3 指标收集与日志聚合的协同设计

指标系统采用拉取模型(Prometheus)时,每个服务需暴露 /metrics 端点,由Prometheus Server定期抓取。对于短生命周期任务(如K8s Job),需使用Pushgateway补充。日志聚合则采用推模型:Filebeat监听容器stdout或日志文件,将数据推送到Kafka缓冲,再由Logstash或Fluentd解析后写入Elasticsearch。

两者协同的关键在于标签统一。指标中的 service、pod、namespace 标签必须与日志中的字段保持一致,否则无法在Grafana中通过同一维度下钻。建议在采集端就完成字段规范化,例如统一使用 k8s.pod.name 而非部分服务用 host、部分用 instance。

维度 分布式追踪 指标收集 日志聚合
数据形态 树状Span 时序数值 JSON文本
采集方式 SDK主动上报 Prometheus拉取 Agent推送
典型存储 Jaeger + ES Prometheus TSDB ES + S3
查询语言 Trace ID检索 PromQL Lucene / KQL
保留周期 7天(热) 30天(降采样) 90天(冷备)

4.4 案例:AI推理服务的全链路监控落地

某AI视觉检测服务部署在K8s集群中,由接入网关 → 预处理服务 → 模型推理服务(GPU)→ 结果回调服务四个环节组成。最初仅监控CPU和内存,导致GPU显存溢出时无法定位瓶颈。重构后采用如下架构:

  1. 追踪层:在网关生成 trace_id,模型推理服务记录GPU kernel执行时间、显存分配量作为Span属性。
  2. 指标层:暴露 gpu_utilization、gpu_memory_used、inference_batch_size 等自定义指标,按 model_version 标签区分。
  3. 日志层:推理失败时输出包含 trace_id、input_shape、error_type 的结构化日志。

某次线上P99延迟从120ms飙升至800ms,通过Grafana查看 gpu_utilization 发现利用率仅30%,但 gpu_memory_used 接近上限。进一步按 trace_id 查询,发现预处理服务在批量组装时发生内存拷贝阻塞,导致GPU等待数据。最终通过优化预处理线程池和增加批量大小解决。

常见误区:不要将日志采集直接写入Elasticsearch而不经过缓冲队列。当业务高峰日志量突增时,ES写入瓶颈会反压到业务进程,导致请求超时。正确做法是引入Kafka作为日志缓冲层,消费速率由ES集群能力决定,与业务解耦。

4.5 架构设计复盘与关键决策

在实施全链路监控时,需避免以下典型错误:

  • 过度埋点:每个方法都创建Span,导致追踪数据量爆炸,存储成本失控。应只对跨服务调用、数据库访问、外部API调用等关键路径埋点。
  • 采样策略单一:固定10%采样会漏掉偶发错误。必须结合错误状态和业务优先级动态调整采样率。
  • 忽略异步边界:消息队列、定时任务、多线程场景下未传递上下文,导致追踪链断裂。需在MQ消息头和线程池的 ThreadLocal 中显式传递。
  • 存储选型不当:将追踪数据存入Prometheus会导致高基数问题(每个Trace ID都是唯一标签),应使用ES或专用追踪存储。

最终架构应满足三个核心能力:5分钟内定位故障服务、10分钟内还原完整调用链、30分钟内关联日志与指标完成根因分析。这需要从采集端就保证数据质量,而非在查询端临时补救。