把你想象成一家“AI 医院”的院长,你的病人是一套线上推荐系统。它不会说话,哪里不舒服全靠你主动检查。一间合格的 ICU 病房至少要配三件设备:墙上的生命体征监护仪、床头的病历本、能注入造影剂的 CT 机。对应到可观测性世界,就是三大支柱——指标(Metrics)、日志(Logs)、追踪(Traces)。光有设备还不够,你还要和病人约定“健康目标”(SLO),并在指标越线时让值班护士被呼叫到(告警)。可设备品牌五花八门:开源自建像社区诊所,商业托管像三甲医院,该买哪几台、先买哪台、三年账单差多少——这就是“可观测性工具链选型”要回答的问题。本文用一间医院从开业到收治大病人的故事,带你走完从三大支柱、工具对比到告警闭环的选型全流程。

岗位关联

对 AI 工程师而言,掌握 SLO 与工具链选型,意味着你能用可量化的指标守住模型服务质量,在故障来临前接到告警,而不是在事故后手忙脚乱翻日志。

目录
  1. 可视化演示
  2. 三大支柱:监护仪、病历与造影
  3. Prometheus 选型:贴墙的生命体征监护仪
  4. Loki 日志平台:会贴标签的病历柜
  5. Jaeger 追踪:给请求打一针造影剂
  6. 方案对比:社区诊所与三甲医院
  7. 选型决策:床位决定设备清单
  8. 告警闭环:呼叫值班医生的那根线
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

展示Metrics/Logs/Traces三大支柱数据流、四阶段采集-传输-存储-可视化管线及渐进式部署路径,步进切换探索。

本节配有交互动效(进入视口后自动加载,约 3KB)。

可观测性三大支柱 Metrics指标采集系统数值状态 Logs日志聚合离散事件记录 Traces追踪分布式请求链路 可观测性 = Metrics + Logs + Traces 三支柱汇聚推断系统内部状态

三大支柱:监护仪、病历与造影

假设你现在是一家 AI 医院的院长,刚收治了一位“病人”——一个线上商品推荐系统。它不会喊疼,出了问题只会沉默地给用户返回一个转圈。这时候你需要三件设备来“问诊”。第一件是挂在墙上的生命体征监护仪:心率、血压、血氧,一眼就看得出病人现在的状态怎么样;第二件是床头的病历本:护士每次巡查都往里记一行,什么时间吃了什么药、体温变化了多少;第三件是能做造影的 CT 机:往血管里注射造影剂,看着它流经每个器官,找出到底堵在哪一站。

这三件设备对应到可观测性领域,正是三大支柱。第一根支柱叫指标(Metrics),是数值型的连续读数,比如每秒请求数 QPS、响应延迟 P95、GPU 利用率——它回答“系统现在怎么了”;第二根支柱叫日志(Logs),是带时间戳的事件记录,每一条都写明了当时发生了什么细节——它回答“为什么会这样”;第三根支柱叫追踪(Traces),是请求从进入到返回的完整路线图——它回答“时间都耗在哪一站”。三者合起来,才能对系统做一次完整的“体检”。

有了这三类数据,我们才能计算一个关键概念:SLI(Service Level Indicator,服务水平指标),即系统实际达到的质量水平。而 SLO(Service Level Objective,服务水平目标)是我们和病人约定的健康底线,比如“99% 的请求延迟小于 300ms”。SLI 是实际值,SLO 是承诺值,两者一比较,就知道健康是否达标。

理解这三根支柱,就像确认病房的三种设备都已到位:监护仪管“现在危不危险”,病历本管“之前发生了什么”,CT 机管“问题到底堵在哪”。任何 AI 系统的可观测性建设,都是从这三根支柱开始的,后面要挑选的具体工具,不过是这三类设备的品牌罢了。

SLI=GV=V−BV×100%\text{SLI} = \frac{G}{V} = \frac{V - B}{V} \times 100\%
  1. 分子 G(好事件数)$G$ 代表窗口内满足质量标准的请求数,比如延迟小于 300ms 的推理调用。
    G=好请求数G = \text{好请求数}
  2. 分母 V(总事件数)$V$ 是窗口内全部合法请求的总数,成功和失败的都算。
    V=总请求数V = \text{总请求数}
  3. 坏事件换算$V - B$ 用总请求数减去坏请求数得到好请求数,这样监控端只需统计坏请求就能实时算出 SLI。
    G=V−BG = V - B
  4. 百分比呈现$\times 100\%$ 把小数值放大成直观的百分比,比如 0.992 写作 99.2%。
    SLI=V−BV×100%\text{SLI} = \frac{V - B}{V} \times 100\%

Prometheus 选型:贴墙的生命体征监护仪

在实际病房里,监护仪不是病人自己报数,而是护士每隔几秒来抄一次读数。Prometheus 也是同样的哲学:它不等待应用推送,而是自己定期通过 HTTP 去“拉取”(Pull)每个服务暴露的指标端点。这套指标拉取模型的好处是,监控方掌握主动权,目标服务挂了会立刻被发现,而不是像往黑洞里推数据那样,连丢没丢都不知道。

Prometheus 把拉到的指标存进自己的时序数据库(TSDB),每一笔数据都是“时间戳 + 指标名 + 标签 + 数值”的格式。查询它要学一门叫 PromQL 的查询语言,比如统计近 5 分钟平均每秒请求数,可以用 rate() 函数;把多个实例的结果加总,则用 sum()。它能成为 AI 团队的首选,还因为自带告警规则引擎和一套服务发现机制——在 Kubernetes 里,新起的模型推理副本会被自动纳入监控范围,不需要人工改配置。

QPS 是 AI 推理服务最核心的指标之一。它并非直接读一个“当前值”,而是把计数器在两个时刻的读数相减再除以时间,这就是速率计算的本质。

在选型上,Prometheus 就像那台最耐用的进口监护仪:社区活跃、资料丰富、与 Kubernetes 天然亲和,是目前 AI 基础设施中指标采集的默认选择。但别忘了,监护仪只会报数字,它不能告诉你病历里的细节,也不负责找值班医生——那些是后面几节故事的内容。

QPS=C(t2)−C(t1)t2−t1\text{QPS} = \frac{C(t_2) - C(t_1)}{t_2 - t_1}
  1. 计数器终点值$C(t_2)$ 是监控时刻 $t_2$ 读到的累计请求计数,比如 100 万次。
    C(t2)=1000000C(t_2) = 1000000
  2. 计数器起点值$C(t_1)$ 是上一时刻 $t_1$ 读到的累计计数,比如 97 万次。
    C(t1)=970000C(t_1) = 970000
  3. 相减得增量$C(t_2) - C(t_1)$ 是窗口内新增的请求数,比如 3 万次。
    C(t2)−C(t1)=30000C(t_2) - C(t_1) = 30000
  4. 除以时间窗口$\div (t_2 - t_1)$ 得到每秒请求数;窗口常取 5 分钟,用来削平瞬间抖动。
    30000300s=100 QPS\frac{30000}{300\text{s}} = 100 \text{ QPS}

Loki 日志平台:会贴标签的病历柜

如果护士把病人的每一次心跳、每一句对话都原样抄进病历,那病历本三天就能堆满一间屋子。聪明的档案室只做一件事:在病历袋的封面上贴几个标签(病人 ID、科室、日期),正文则原封不动塞进仓库。要查的时候,先按标签筛出十几个档案袋,再打开翻找正文。Loki 的设计思想正是如此:它不给日志全文建索引,而只对标签(比如 app="rag"、level="error")建立索引,日志正文则被压缩后存进廉价的对象存储。

这套标签索引设计带来了极低的存储成本,也决定了它的查询方式:先用标签缩小范围,再用 LogQL 语法在结果里筛选关键词。例如 {app="rag"} |= "recall_failed" 就是“在 rag 这个应用的日志里,找到包含 recall_failed 的行”。因为 Loki 是 Grafana 家族成员,你可以在同一个 Grafana 面板上,把 Prometheus 的指标曲线和 Loki 的日志行并排展示——指标报警后点一下就能跳到对应的原始日志,排障路径非常顺滑。

选型时要估算存储成本,因为日志量常常超乎预期。一个估算公式可以帮助我们在采购前算清账单。

Loki 就像一个会贴标签的病历柜:便宜、量大、检索方便。它不适合做精确的数值统计,也不负责追踪链路,但在“出问题时翻旧账”这个场景里,它是成本最低、最顺手的选择。

Storage=R×L×T\text{Storage} = R \times L \times T
  1. 日志速率 R$R$ 是每秒写入的日志条数,比如 2000 条/秒。
    R=2000 条/sR = 2000 \text{ 条/s}
  2. 单条平均体积 L$L$ 是每条日志压缩后的平均字节数,比如 200 字节。
    L=200 B/条L = 200 \text{ B/条}
  3. 保留时间 T$T$ 是日志需要保存的秒数,比如 30 天。
    T=30×86400=2592000 sT = 30 \times 86400 = 2592000 \text{ s}
  4. 三者相乘得到总存储量约 1TB;Loki 靠压缩与对象存储把 $L$ 压得很低。
    Storage=2000×200×2592000≈1 TB\text{Storage} = 2000 \times 200 \times 2592000 \approx 1 \text{ TB}

Jaeger 追踪:给请求打一针造影剂

CT 检查时,医生往血管里打一针造影剂,然后看着它在 CT 片子上流经每个器官:在哪个器官停留久了,哪儿就有问题。Jaeger 做的正是这件事:当一个 AI 请求进来,它给这个请求分配一个全局唯一的 trace ID(造影剂),请求每经过一个服务(网关、鉴权、向量检索、大模型推理),就留下一个 span(扫描切片),记录进入和离开的时间。所有切片按 trace ID 拼在一起,就还原出一条完整的调用链——这就是“分布式追踪”。

全量追踪的代价极大:一个高并发服务每秒可能有几十万个请求,若每个都记录,存储会迅速失控。因此 Jaeger 采用调用链采样策略,最常用的是概率采样,比如只记录 10% 的请求。很多人担心“漏掉故障”,其实只要采样是随机的,统计规律依然成立——我们要找的不是某一条请求,而是整条链路上的统计规律。

Jaeger 的另一个价值是依赖分析图:它能把服务间的调用关系画成一幅拓扑图,一眼看出哪个服务被调用最频繁,也可以做瓶颈定位——找到 self-time(自身耗时)最长的那个 span,那就是造影剂“堵住”的地方。如今标准的做法是通过 OpenTelemetry(OTel)统一生成和传播追踪数据,Jaeger 只是后端存储展示的选项之一。给请求打造影剂,是现代微服务 AI 系统定位性能瓶颈的必备手段。

μ^=1n∑i=1nxi\hat{\mu} = \frac{1}{n} \sum_{i=1}^{n} x_i
  1. 样本 x_i$x_i$ 表示被采样到的第 $i$ 个请求的延迟值。
    xi=第 i 个样本的延迟x_i = \text{第 } i \text{ 个样本的延迟}
  2. 样本量 n$n$ 是采样窗口内保留的请求总数,比如 1 万个。
    n=10000n = 10000
  3. 求和再平均$\frac{1}{n}\sum_{i=1}^{n} x_i$ 是样本均值,在随机采样下能近似真实延迟分布。
    μ^=x1+x2+⋯+xnn\hat{\mu} = \frac{x_1 + x_2 + \cdots + x_n}{n}
  4. 帽子记号$\hat{\mu}$ 表示这是一个估计值而非精确值,采样率越低误差越大。
    采样率 10%⇒误差可接受\text{采样率 } 10\% \Rightarrow \text{误差可接受}

方案对比:社区诊所与三甲医院

当你决定给医院配设备时,面前有两条路。第一条是开源自建:Prometheus、Loki、Jaeger 再加上 Grafana 面板,相当于自己开一家社区诊所——设备免费送,但安装、调试、保修全得自己来;第二条是商业托管方案,比如 Datadog、Grafana Cloud、New Relic,相当于签约三甲医院——开箱即用、有 24 小时客服,但每个月都会收到账单,数据量涨,账单也涨。

从功能矩阵看,开源三件套和商业方案的“能力”其实不相上下:指标、日志、追踪、告警,大家都能做。真正的差异在运维成本。开源方案的价值不是“免费”,而是“按需付费”:你为它花的每一份人力,都变成了对系统的理解。商业方案的卖点也不是“功能多”,而是“省心”:把存储扩容、升级打补丁、高可用这些苦活外包出去。选型时算总账,不能只看采购价,三年总拥有成本(TCO)才是公平的比较口径。

社区诊所自己的设备修多了,你也会成为设备专家;三甲医院账单贵,但能让你把精力留给病人而不是修机器。选择没有绝对的对错,只有和团队能力匹配与否——如果你只有两个工程师还要维护几十个微服务,那商业方案省下的人力可能远比账单值钱。

TCO=Clicense+Cstorage+Cops×Nengineer\text{TCO} = C_{\text{license}} + C_{\text{storage}} + C_{\text{ops}} \times N_{\text{engineer}}
  1. 授权成本$C_{\text{license}}$ 是商业方案按节点或数据量收取的订阅费,开源方案该项为零。
    Clicense=订阅费/年C_{\text{license}} = \text{订阅费/年}
  2. 存储成本$C_{\text{storage}}$ 是对象存储、磁盘与带宽的月度费用。
    Cstorage=存储量×单价C_{\text{storage}} = \text{存储量} \times \text{单价}
  3. 人工成本$C_{\text{ops}} \times N_{\text{engineer}}$ 是每个工程师的运维工时折算,乘以投入人数。
    Cops×N=人月工资×人数C_{\text{ops}} \times N = \text{人月工资} \times \text{人数}
  4. 求和比较把三项相加比较三年总账,才能公平对比开源与商业。
    TCO开源<TCO商业⇒开源胜出\text{TCO}_{\text{开源}} < \text{TCO}_{\text{商业}} \Rightarrow \text{开源胜出}

选型决策:床位决定设备清单

社区诊所不会开业第一天就买 MRI。选型决策的第一原则是:床位决定设备,规模决定投入。一个 5 人 AI 团队,核心任务是尽快把模型跑起来,此时整套商业平台是负担,自建一套精简的 Prometheus + Grafana 就够用;一个 50 人的平台团队,服务数量多、跨部门协作频繁,需要补上 Loki 日志和 Jaeger 追踪,并考虑成熟的告警流程;而到了 500 人的规模,自建成本开始失控,商业方案的一站式集成和服务支持可能反而更划算。

第二个原则是技术栈兼容性:如果全家桶都在 Kubernetes 上,Prometheus 和 Loki 与 K8s 的亲和力就是巨大优势;如果团队已经重度使用某个云厂商,那么该云厂商的托管可观测服务(如 Managed Prometheus)能省掉大量维护工作。第三个原则是数据量评估:先粗算每秒日志条数、每秒指标点数和采样率,再对照存储公式估算成本,避免上线三个月后被账单或磁盘打垮。

把多个候选工具放在一起比较时,可以用一个加权评分模型来辅助决策:给每个维度打分,乘上权重,最后排序。

最稳妥的决策往往不是“一步到位”,而是渐进式落地:先上 Prometheus 盯住核心指标,同步设计告警规则形成闭环;等排障时发现“查不到上下文”,再引入 Loki;等定位跨服务瓶颈力不从心时,再接入 Jaeger。小步快跑,每次只解决一个痛点,选型自然水到渠成。

Scorej=∑i=1nwi×sij,∑i=1nwi=1\text{Score}_j = \sum_{i=1}^{n} w_i \times s_{ij}, \quad \sum_{i=1}^{n} w_i = 1
  1. 方案得分$\text{Score}_j$ 是第 $j$ 个候选工具的综合得分。
    Scorej=w1s1j+w2s2j+⋯\text{Score}_j = w_1 s_{1j} + w_2 s_{2j} + \cdots
  2. 维度分$s_{ij}$ 是工具 $j$ 在维度 $i$(如采集能力、易用性、社区活跃度)上的评分。
    sij∈[1,5]s_{ij} \in [1, 5]
  3. 权重$w_i$ 是各维度的重要性,所有权重之和为 1。
    ∑i=1nwi=1\sum_{i=1}^{n} w_i = 1
  4. 加权求和得分最高者胜出;权重由团队当前目标决定,比如重视成本就把“运维成本”维度的权重调高。
    Scorej=∑wisij\text{Score}_j = \sum w_i s_{ij}

告警闭环:呼叫值班医生的那根线

监护仪报警本身不是目的,最终要把值班医生叫到病床前。告警体系就是那根从监护仪连到值班室的线。在 Prometheus 生态里,这根线的中枢叫 Alertmanager。它的第一个职责是告警规则设计:规则要尽量基于 SLO 错误预算来设置,而不是对每个指标设死阈值。比如“错误预算剩余不足 20%”是一个有业务含义的告警,而“CPU 大于 80%”很容易在业务低峰期制造噪音。

Alertmanager 的第二个职责是抑制与静默。抑制的意思是,当机房整体宕机这类的“大告警”触发时,自动屏蔽它下面几百个主机的小告警,避免值班手机被轰炸;静默则是维护窗口期的主动屏蔽,比如发版期间明确告诉系统“这段时间的告警我知道了,别打扰”。第三个职责是分级路由:把 P0 级告警立刻打电话给值班人,把 P2 级告警合并成一条邮件第二天再看。

告警的最终目标是让值班人知道“预算还能撑多久”,从而决定是否回滚、是否扩容。这个倒计时可以用一个简单公式计算。

至此,我们这间 AI 医院的设备清单就完整了:三大支柱采集“体征”,SLO 约定“健康底线”,工具链按规模渐进铺设,告警闭环把异常第一时间送达值班医生。设备不在多,而在配套;可观测性的终点不是满墙的大屏,而是每一次铃声响起时,值班医生都知道自己该去哪一站。

Texhaust=Eleftbper dayT_{\text{exhaust}} = \frac{E_{\text{left}}}{b_{\text{per day}}}
  1. 剩余预算$E_{\text{left}}$ 是当前错误预算余量,比如 0.4%。
    Eleft=0.004E_{\text{left}} = 0.004
  2. 每日消耗速率$b_{\text{per day}}$ 是按当前劣化速度每天消耗的预算百分比,比如 0.15%。
    bper day=0.0015b_{\text{per day}} = 0.0015
  3. 相除得天数预算耗尽倒计时约为 2.7 天,若小于 1 天需立即叫停发布。
    Texhaust=0.0040.0015≈2.7 天T_{\text{exhaust}} = \frac{0.004}{0.0015} \approx 2.7 \text{ 天}
  4. 告警触发点配合“余量 < 20% 发 warning”的阈值,在预算耗尽前介入。
    余量<0.2×(1−SLO)⇒warning\text{余量} < 0.2 \times (1 - \text{SLO}) \Rightarrow \text{warning}

AI 应用场景

LLM 推理服务的 SLO 实时监控

阶段:部署与运营

解决的问题:传统方式等用户投诉“变慢了”才去排查,问题感知滞后。用 Prometheus 采集每路 token 的生成延迟、QPS 和错误率,对照预先约定的 SLO(如 99% 请求延迟 < 300ms)计算实时错误预算,预算消耗过快时自动告警。

具体案例:某大模型 API 团队发布新量化版本后,监控面板显示 P95 延迟从 180ms 升到 320ms,错误预算一天消耗 0.6%,触发 warning 告警。团队依据预算倒计时公式判断还有约 3 天余量,从容回滚模型并定位到量化精度异常,而不是等用户骂上门。

RAG 应用排障:日志定位“答非所问”

阶段:故障排查

解决的问题:RAG 应用“答非所问”时,传统排查要人肉翻几十个服务的日志。用 Loki 采集检索关键词、命中文档数和召回分数,按 trace_id 过滤日志,快速定位问题出在召回阶段还是生成阶段。

具体案例:某客服机器人接入新知识库后准确率骤降,工程师用 LogQL 检索 {app="rag"} |= "recall_failed",发现向量库连接超时率高达 23%,进一步结合 Jaeger 链路看到超时集中在 embedding 服务,五分钟内完成定位。

训练管道追踪:找出 GPU 挨饿的元凶

阶段:训练与调优

解决的问题:分布式训练中 GPU 利用率低,传统方式只能看到“GPU 不忙”,却不知道时间耗在哪。用 Jaeger 追踪数据预处理、加载、前向、反向的调用链,定位瓶颈 span。

具体案例:某大模型训练团队通过 Jaeger 依赖分析图发现,GPU 等待数据加载器的时间占 68%,即“GPU 挨饿”。据此把 TFRecord 预读取和缓存策略改为异步流水线,训练吞吐提升 1.8 倍。

Python 演示

python57 行
#!/usr/bin/env python3# -*- coding: utf-8 -*-"""蒙特卡洛模拟:AI推理延迟逐日劣化时,SLO错误预算如何消耗并触发告警。"""import random  class SloMonitor:    """SLO监控器:统计坏请求数量,实时换算SLI与剩余错误预算。"""     def __init__(self, target=0.99, limit=300):        self.target = target        self.limit = limit        self.total_count = 0        self.bad_count = 0     def observe(self, latency):        self.total_count += 1        if latency >= self.limit:            self.bad_count += 1     def sli(self):        if self.total_count == 0:            return 1.0        return 1.0 - self.bad_count / self.total_count     def budget_left(self):        return self.sli() - self.target     def alert_level(self):        left = self.budget_left()        if left <= 0:            return "critical: 错误预算耗尽,立即响应"        if left < 0.2 * (1.0 - self.target):            return "warning: 预算不足20%"        return "healthy: 预算充裕"  def simulate_day(mon, day_index, rps=10, hours=12):    """模拟半天流量:延迟均值随day_index逐步劣化。"""    for _ in range(rps * hours * 3600):        latency = random.gauss(120, 25) + day_index * 20        mon.observe(max(0, latency))  def main():    random.seed(2024)    mon = SloMonitor(target=0.99, limit=300)    for d in range(1, 9):        bad_before = mon.bad_count        simulate_day(mon, d)        day_bad = mon.bad_count - bad_before        print("第%d天 当日坏请求=%5d 累计SLI=%.5f 剩余预算=%+.5f -> %s"              % (d, day_bad, mon.sli(), mon.budget_left(), mon.alert_level()))  if __name__ == "__main__":    main()
目的:模拟一个 AI 推理服务连续 8 天的请求流量,延迟均值每天劣化 20ms,观察 SLO 错误预算从健康走向 warning 再到 critical 的完整过程。
  1. def __init__(self, target=0.99, limit=300):初始化监控器,默认 SLO=99%、延迟阈值 300ms
  2. self.total_count += 1每来一个请求,总计数加一
  3. if latency >= self.limit:超过 300ms 的请求记为坏事件
  4. return 1.0 - self.bad_count / self.total_countSLI = 好请求占比
  5. return self.sli() - self.target剩余预算 = 实际可用性 − 承诺 SLO
  6. random.gauss(120, 25) + day_index * 20延迟均值随天数劣化,模拟服务“逐渐生病”
  7. random.seed(2024)固定随机种子,让演示结果可复现

常见误区

误区我部署了 Prometheus 和 Grafana,能看到 CPU 和内存曲线,大屏也好看,这样应该就算可观测了吧?

正解监控工具只是“采集设备”,可观测性的核心是“能用数据回答问题”:你的 SLO 是多少?错误预算还剩多少?延迟变慢是为什么?如果没定义 SLO、没接告警闭环,仪表盘只是一块装饰墙,就像病房里装了监护仪却没人知道正常心率是多少。

为何常见:工具安装后立刻有图表输出,视觉上“很完整”,让人误以为工作已结束,而定义 SLO 这种看不见的功夫容易被忽略。

误区把所有日志都原样存下来,出问题时总能查到,反正磁盘便宜,多存点没坏处。

正解日志量是无限的,存储成本和检索速度会随量级急剧恶化。Loki 的设计哲学就是“只索引标签、正文压缩存储”——先按标签大幅缩小范围,再翻正文。日志应该分级:高价值日志保留 30 天,调试日志保留 3 天,无穷无尽的 debug 输出该丢就丢。

为何常见:人们天然恐惧“丢数据”,却忽略了噪声数据会淹没真正的信号,且账单不会说谎。

误区采样会漏掉故障现场,必须给每个请求都做追踪,一条都不能少。

正解全量采样在每秒几十万请求的服务上会瞬间击溃存储。随机采样下,样本均值依然能准确估计延迟分布;况且排障时还可以对错误请求提高采样率(尾采样),做到“故障不丢、成本可控”。怕漏,是没理解统计推断的价值。

为何常见:故障发生时人总希望“当时的完整记录”在手里,这是典型的损失厌恶,而不是成本理性。

误区追踪信息最全,能看到每一条链路的每一站,不如直接上 Jaeger,把指标和日志都省了。

正解三大支柱回答的是不同问题:指标告诉你“系统整体健康坏了”,日志告诉你“具体发生了什么事”,追踪告诉你“时间耗在哪一站”。追踪只能覆盖被采样的请求,没法给出 QPS 趋势这类全局数字;日志则保留了指标准备不出的原始细节。三者在排障中互相补充、缺一不可。

为何常见:新手接触追踪后容易被它的“上帝视角”震撼,误以为它能一统天下,忽视了三类数据各自的不可替代性。

误区公司预算充足,买了 Datadog 就一劳永逸,运维团队可以撒手不管了。

正解商业方案省去的是存储扩容、组件升级等“基础设施运维”,但指标命名规范、日志采集端配置、告警规则设计、成本治理这些“上层运维”依然要自己做。如果埋点混乱,再贵的平台也只是昂贵的垃圾收集器;账单也可能随数据量失控,需要设置采样率和保留期来治理成本。

为何常见:销售宣传总是强调“全托管、零运维”,让人误以为把数据倒进去就自动获得可观测性,忽略了数据质量才是真正的成本。

面试题

Q1. 可观测性的“三大支柱”指的是下列哪一组?

单选题 · easy

  • A.指标、日志与链路追踪← 正确答案
  • B.监控、告警与可视化
  • C.指标、告警与自动扩容
  • D.日志、审计与安全合规

答案:A。三大支柱是 Metrics(指标)、Logs(日志)、Traces(追踪),分别回答“怎么了”“为什么”“在哪一站”。B 中告警与可视化属于上层应用而非数据支柱;C 和 D 混淆了运维流程概念。

Q2. Prometheus 采集指标时主要采用的方式是?

单选题 · easy

  • A.应用进程主动把数据推送到服务器
  • B.服务器定期通过 HTTP 拉取指标端点← 正确答案
  • C.通过数据库同步把查询结果导入
  • D.依赖人工手工填写监控数据报表

答案:B。Prometheus 是拉取(Pull)模型,像护士定时抄读数一样,通过 HTTP 定期抓取目标服务的 /metrics 端点。推送模型(Push)在 Prometheus 生态中属于例外场景(如短生命周期任务经 Pushgateway)。

Q3. Loki 控制日志存储成本的核心设计是什么?

单选题 · mid

  • A.对日志全文建立倒排索引以加速搜索
  • B.只对标签建立索引,日志正文压缩存储← 正确答案
  • C.超过七天的日志自动删除不留任何副本
  • D.写入前随机丢弃一半日志样本数据

答案:B。Loki 只在封面贴标签(对 label 建索引),正文像病历原稿一样压缩进对象存储。A 是 Elasticsearch 的全文索引思路,成本高;C 会丢失排障数据;D 的随机丢弃会让日志残缺不可信。

Q4. 关于 trace 与 span 的关系,下列说法正确的是?

单选题 · mid

  • A.一个通信链路 trace 由多个 span 组合而成← 正确答案
  • B.一个 span 由多个互相独立的 trace 聚合而成
  • C.trace 与 span 是完全等价的两个不同叫法
  • D.trace 只存在于日志中而不存在于指标中

答案:A。一次请求的完整调用链叫 trace,其中每一次跨服务调用或内部处理记录叫 span;多个 span 按父子关系组合成一棵 trace 树。B 方向反了,C 混淆层级,D 错误——trace 是独立于日志和指标的数据类型。

Q5. 某服务 SLO = 99%,月末错误预算剩余 25%,这说明?

单选题 · mid

  • A.本月实际可用性大约为 99.25%← 正确答案
  • B.本月实际可用性大约为 99.75%
  • C.本月实际可用性大约为 25.00%
  • D.本月已发生大量 SLA 违约赔偿事件

答案:A。错误预算总量是 1 - SLO = 1%。剩余 25% 表示只消耗了 0.75%,因此 SLI = 99% + 0.25% = 99.25%。B 对应剩余 75% 的情况;C 把预算剩余直接当可用性;D 方向相反,预算充足说明没有违约。

Q6. 下列哪些属于告警闭环的组成部分?

多选题 · mid

  • A.告警分级路由与优先级设定← 正确答案
  • B.抑制与静默维护窗口机制← 正确答案
  • C.值班人员升级响应流程← 正确答案
  • D.日志文件滚动与压缩归档

答案:ABC。告警闭环指从规则触发、Alertmanager 分组抑制、按优先级路由到值班人,再到升级响应的完整流程。D 是日志存储管理,属于 Loki 的运维范畴,与告警闭环无关。

Q7. 用 PromQL 统计最近 5 分钟的平均 QPS,正确的写法是?

单选题 · hard

  • A.sum(rate(http_requests_total[5m]))← 正确答案
  • B.sum(http_requests_total[5m])
  • C.avg(http_requests_total[5m])
  • D.max(rate(http_requests_total))

答案:A。QPS 是速率,必须用 rate() 结合时间窗口计算每秒增量,再用 sum() 聚合多个实例。B 只求总和不是速率;C 对计数器求平均没有速率含义;D 的 rate() 缺少时间窗口参数,无法计算。

Q8. 一个 5 人 AI 团队建设可观测性,合理的渐进式路径是?

多选题 · hard

  • A.先用 Prometheus 覆盖核心推理服务的指标← 正确答案
  • B.首周内采购并部署全套商业可观测平台
  • C.排障遇到检索瓶颈时再引入 Loki 日志← 正确答案
  • D.同步设计基于 SLO 的告警规则形成闭环← 正确答案

答案:ACD。小团队应小步快跑:先指标、再告警闭环,按需补日志和追踪(A、C、D)。B 的全套商业平台对 5 人团队是负担——设备再好,没医生会用也是浪费,渐进式建设远比一步到位稳妥。

Q9. 关于 OpenTelemetry(OTel)的说法,正确的是?

单选题 · hard

  • A.提供统一标准的 SDK 用于生成与传播追踪数据← 正确答案
  • B.是 Prometheus 专属的日志查询语言规范
  • C.是 Jaeger 内置的闭源商业采样算法
  • D.功能仅限于替代 Grafana 完成图表渲染

答案:A。OTel 是 CNCF 的开源可观测性标准,提供统一 SDK 生成指标、日志、追踪数据并传播 trace 上下文,可对接 Jaeger、Prometheus 等多种后端。B 说的是 LogQL,C 与事实相反,D 把采集标准和可视化工具混为一谈。

Q10. 告警抑制(inhibition)的典型应用场景包括?

多选题 · easy

  • A.机房整体故障时屏蔽其下所有主机告警← 正确答案
  • B.已触发高优告警时静默同类低优告警← 正确答案
  • C.把多个同主题告警合并成一条通知发送
  • D.按值班表把告警动态分发到不同责任人

答案:AB。抑制就是用高层级告警压制低层级告警,避免告警风暴,如机房宕机屏蔽主机告警(A)、高优已触发则静默同类低优(B)。C 是分组(grouping),D 是路由(routing),都是 Alertmanager 的其他功能,不属于抑制。