面试考察点
- 是否从 SLO 和用户影响出发,而不是只列工具。
- 能否说明指标、日志、追踪和事件的互补关系。
- 是否控制标签基数、采样、成本和敏感数据。
核心答案
指标用于快速发现趋势和告警,结构化日志提供离散事件细节,分布式追踪还原一次请求的跨服务路径,业务事件解释技术指标背后的用户影响。设计应从 SLI/SLO、关键用户旅程和故障假设出发,确保告警能指向可执行的排查入口。
常用入口指标可围绕请求量、错误、延迟和资源饱和度,并按服务依赖继续下钻。
上下文关联
请求在边界生成或接收 trace id,在服务、消息和异步任务间传播;日志记录 trace id、业务操作 id 和稳定错误码。消息链路还要保留原 trace 关系或 link,避免异步后完全断链。
从 SLO 反推信号
先定义“用户是否成功”:例如支付请求成功率、搜索 P99、消息端到端延迟、配置生效时间。再建立对应 SLI:请求量、错误、延迟、饱和度、Lag、版本差异等。仅采集 CPU、内存和 JVM GC 不能说明用户是否受影响;同样,接口 200 也可能返回业务失败。
用户旅程 SLO -> 服务 SLI -> 依赖指标 -> 日志/trace 证据 -> 可执行告警
告警应表达“预算正在消耗且需要动作”,例如过去 10 分钟 P99 超过阈值并影响 5% 请求,而不是每个 Pod CPU 短暂升高都通知值班人员。
指标设计与高基数
指标标签适合有限集合:service、route template、status class、region、instance;不要把 user_id、order_id、完整 URL、异常堆栈放成 Prometheus label,这会造成时间序列爆炸。高基数字段进入结构化日志或 trace span,按需检索。
请求指标至少区分成功/业务拒绝/系统错误、路由模板和依赖;队列类系统同时记录入口速率、处理速率、当前积压和最老消息年龄。资源指标要和容量上限关联,而不是只画当前值。
结构化日志规范
{
"timestamp":"2026-07-22T10:00:00Z",
"level":"WARN",
"service":"order-api",
"trace_id":"t-01",
"operation_id":"op-1001",
"error_code":"INVENTORY_TIMEOUT",
"duration_ms":312,
"retry_count":1
}
日志应可机器解析,字段命名稳定,敏感信息脱敏,避免把 token、身份证、支付数据和完整请求体写入。错误码比自然语言更适合聚合;堆栈应在最有上下文的边界记录一次。
Trace 的采样策略
全量 trace 对高吞吐服务成本很高,可保留错误、慢请求、关键交易和随机代表样本。采样决定要在入口保持一致,否则一条请求在下游突然丢失。异步消息使用 parent/links 传播,批量处理要注意一个 span 包含多少消息,避免产生海量子 span。
告警与成本
告警优先基于用户可感知 SLO 消耗和持续异常,减少瞬时噪声。高基数字段不能直接做指标标签,明细进入日志或追踪;采样要保留错误、慢请求和关键业务,并设置数据保留层级。
常见误区
日志越多不等于可观测性越好,无结构、无上下文和重复堆栈只增加成本。平均延迟会掩盖长尾,应关注分位数、错误预算和分组后的异常差异。
告警到排障闭环
告警 -> 确认用户影响/变更时间 -> 看入口 P99/错误预算
-> trace 找慢依赖 -> 日志核对错误码与参数
-> 指标验证容量/资源 -> 止损/修复 -> 验证 SLO 恢复
告警页面应提供 dashboard、最近发布、关联 trace 查询和 runbook 链接。故障结束后记录检测时间、定位时间、恢复时间、误报和缺失信号,推动新增监控而非只扩大日志量。
成本和保留
按数据价值分层保留:指标保留长周期用于趋势,错误和慢 trace 保留更久,普通 debug 日志短期采样;冷热存储、压缩和脱敏都要纳入预算。可观测性系统本身也需要限流,避免故障风暴把日志平台打崩。
高频追问与参考回答
追问:线上故障如何从告警开始定位?
先确认用户范围和变更时间线,再按入口指标定位服务与依赖,通过 trace 找慢点或错误点,用结构化日志验证具体失败,最后用业务指标确认恢复。
追问:为什么不把所有请求都采全量 Trace?
成本、存储、网络和查询压力可能随流量线性增长。应优先保留错误、慢请求、关键交易和代表样本,并保证跨服务采样策略一致。
追问:日志里应该记录完整请求体吗?
通常不应。敏感信息、超大 payload 和个人数据会带来安全与成本风险;应记录稳定操作 ID、摘要、错误码和必要字段,调试数据使用受控采样。
追问:业务指标和技术指标冲突怎么办?
先确认口径和时间窗口。例如接口 200 但支付成功率下降,说明技术健康指标没有覆盖业务结果;应把业务事件和技术 trace 关联起来定位。
追问:指标告警为什么会疲劳?
阈值过多、没有用户影响、没有去重和恢复条件都会产生噪声。以 SLO/错误预算为核心,按持续时间和影响范围触发可执行告警。
总结
可观测性不是数据采集项目,而是“发现、定位、解释、恢复验证”的工程闭环,并受成本和隐私约束。
机制全景图
下面把「分布式系统的可观测性应该如何设计?」从输入到结果压缩成一条可复述的主链路。面试时先用图建立全局坐标,再进入局部实现,能避免只背零散结论。
flowchart LR
A["请求进入生成 Trace/Request ID"]
A --> B["各服务记录结构化日志"]
B --> C["采集指标与分布式 Span"]
C --> D["关联发布和业务事件"]
D --> E["告警定位并驱动处置"]
完整链路:从输入到结果
沿着「请求进入生成 Trace/Request ID → 各服务记录结构化日志 → 采集指标与分布式 Span → 关联发布和业务事件 → 告警定位并驱动处置」观察输入、状态与输出,下面每个阶段都对应一个可以在源码、日志或系统表中验证的位置。
1. 请求进入生成 Trace/Request ID
入口生成或接受可信请求标识,并在日志、消息和下游调用中传播,避免链路断点。
2. 各服务记录结构化日志
日志记录离散事件和上下文,必须结构化、分级并控制敏感字段与高基数。
3. 采集指标与分布式 Span
指标适合趋势和告警,Trace 展示单请求因果与耗时;三者不能互相完全替代。
4. 关联发布和业务事件
发布、配置、扩容和业务活动作为事件叠加到时间轴,能快速判断相关性。
5. 告警定位并驱动处置
告警应从 SLO 与用户影响出发,包含负责人、Runbook 和可执行上下文,避免只报 CPU 高。
源码与实现定位
| 入口 | 阅读重点 |
|---|---|
| OpenTelemetry semantic conventions | Trace/Metric 属性 |
| SLO burn-rate rule | 用户影响告警 |
源码或系统表应按上表顺序追踪:先确认入口实际走到哪条路径,再用运行时数据验证,而不是仅凭类名或配置推测。
参数配置与可复现实验
http.server.request.duration{service,route,status}
trace_id/request_id/tenant_id/release_version
注入单租户错误、慢依赖和发布回归,验证能从告警到 Trace 再到日志。
验证步骤与预期结果
1. 固定输入和基线
先在没有故障注入的环境执行上述配置,固定数据规模、并发度、运行时版本和预热时间。以「错误 Trace 完整率」为主基线,记录值应满足「记录活动/稳态基线」;同时保存 RED/USE 指标、SLO burn rate,使后续变化能够回到同一时间轴比较。
2. 从实现入口确认路径
在「OpenTelemetry semantic conventions」确认请求确实进入「Trace/Metric 属性」对应的实现,再沿「SLO burn-rate rule」观察「用户影响告警」。如果入口路径都未命中,就不应继续调整下游参数,而应先检查调用条件、版本或路由是否与假设一致。
3. 注入本文特有的失败模式
优先复现「日志高基数字段导致成本失控」,并把单一变量逐级放大,直到「错误 Trace 完整率」越过「超过容量或 SLO」。随后再分别验证「只监控资源不监控业务成功率」和「Trace 采样漏掉稀有错误且无错误保留策略」,三类故障分开执行,避免多个变量同时变化而无法归因。
4. 执行止损和根因修复
第一轮只应用「错误与长尾优先采样」,确认它能控制影响范围;第二轮应用「限制高基数标签」,验证核心链路恢复;最后落实「告警带 owner/runbook/release」,消除同类问题再次出现的条件。每一步都保留变更前后数据,不用“感觉变快了”替代测量。
5. 通过退出条件
实验只有同时满足三项才算通过:「错误 Trace 完整率」回到「记录活动/稳态基线」、「端到端 P99」回到「小于预算」、「状态差异」回到「0」,并且业务结果差异为零。若性能恢复但结果不一致,仍应视为失败;若指标恢复后很快再次越线,则说明只完成了临时止损,没有消除根因。
量化基线
| 指标 | 样例基线/口径 | 风险线 | 结论 |
|---|---|---|---|
| 错误 Trace 完整率 | 记录活动/稳态基线 | 超过容量或 SLO | 触发降级 |
| 端到端 P99 | 小于预算 | 突破预算 | 停止扩量 |
| 状态差异 | 0 | 任意非零 | 补偿并对账 |
这些数值是实验口径或示例告警线,不是可复制到所有系统的固定答案;上线阈值应由本系统稳态、峰值和故障演练共同确定。
事故复盘:接口错误率升高却无法定位租户
日志只有异常堆栈,没有 tenant_id、request_id 和发布版本;指标又只按全局聚合。补齐统一上下文、按受控维度拆分 RED 指标并串联 Trace 后,发现单租户异常输入触发。
| 失败模式 | 首要证据 | 第一处置动作 |
|---|---|---|
| 日志高基数字段导致成本失控 | RED/USE 指标 | 错误与长尾优先采样 |
| 只监控资源不监控业务成功率 | SLO burn rate | 限制高基数标签 |
| Trace 采样漏掉稀有错误且无错误保留策略 | Trace 完整率 | 告警带 owner/runbook/release |
发布与回滚检查点
- 发布前:确认「OpenTelemetry semantic conventions」对应实现和上述配置在目标版本仍然有效,并保存「错误 Trace 完整率」基线。
- 灰度中:同时观察 RED/USE 指标、SLO burn rate、Trace 完整率;任一指标越过表中风险线,就停止继续扩量。
- 回滚时:先执行「错误与长尾优先采样」控制影响,再回退代码或参数;涉及持久状态时必须额外核对结果差异。
- 发布后:至少覆盖一个完整峰值周期,确认「日志高基数字段导致成本失控」没有再次出现,才关闭变更观察窗口。
方案对比与选型
| 方案 | 更适合的场景 | 主要收益 | 代价与边界 |
|---|---|---|---|
| 日志 | 离散错误与详细上下文 | 证据丰富、可审计 | 成本高且全文检索慢 |
| 指标 | 趋势、聚合和告警 | 存储高效、适合 SLO | 高基数受限,细节少 |
| Trace | 跨服务因果与单请求长尾 | 定位链路瓶颈 | 采样、上下文传播与成本 |
选型至少带上 峰值流量、数据规模、依赖容量、一致性目标和故障预算,并用上面的量化基线验证;未知数据应明确为待测假设。
设计边界与工程取舍
可观测性不是“收集更多数据”,而是让系统内部状态能被外部证据解释;每个信号都应服务一个诊断或决策问题。
工程落地遵循:先定义 SLO 与不变量,再通过限流、隔离、异步和补偿保护核心链路。回答时直接引用「OpenTelemetry semantic conventions」、配置实验和事故数据,比复述固定模板更有说服力。