可观测性驱动开发(OOD,Observability-Driven Development)正在成为微服务时代保障系统可靠性的新方法论。它把”可观测性”从上线后的补救动作,前置成写代码前就要回答的设计约束:先想清楚要观测什么、用什么指标度量成功,再动手写业务代码。
一、可观测性驱动开发到底是什么
传统做法是”先写功能,出了问题再看日志”。OOD 反转了这个顺序:在需求评审阶段就把”成功怎么被观测到”写进验收标准。一个接口上线前,团队已经清楚它的核心 SLI(成功率、延迟、饱和度)会被怎么采集、告警会怎么触发。这让可观测性成为一等公民,而不是事后补的监控面板。
它和 DevOps、SRE 一脉相承,但更聚焦”开发侧”:你不需要等事故来倒逼埋点,而是在第一次提交时就带上指标、链路和日志。前面我们已经系统梳理过 OpenTelemetry 链路追踪 的接入方式,OOD 正是把这类能力变成编码习惯。
一个常见的反面教材是:团队花两周写完一个下单链路,上线后才发现没有任何成功率埋点,第一次超时只能靠用户投诉定位。OOD 要消灭的正是这种”上线即盲飞”——在写第一行业务逻辑前,先回答”我怎么知道它活着”,把指标当成接口契约的一部分。
二、为什么一定要先定 SLO
很多团队说”我们要高可用”,但”高”是多高?99% 和 99.9% 的可用性,一年允许的宕机时间相差近 9 倍。没有量化的目标,可靠性就变成了永远在和运维吵架的模糊口号。SLO(Service Level Objective,服务水平目标)把”好”定义成一组可验证的数字,让产品、研发、SRE 对同一把尺子负责。
SLO 的价值不在”达标”,而在它倒逼你思考:哪些用户旅程最关键?失败长什么样?当目标真的被打破时,谁该被叫醒?这恰好和我们讲过的 On-call 值班与告警治理 衔接——SLO 决定”该不该告警”,告警治理决定”怎么告警才不被忽略”。
三、SLI、SLO 与错误预算的关系
三者是层层递进的关系,很多新手会把它们混为一谈,这里用一张表厘清:
| 概念 | 英文 | 是什么 | 谁定义 |
| SLI | Service Level Indicator | 真实度量值,如请求成功率 | 研发 + SRE |
| SLO | Service Level Objective | SLI 的目标阈值,如成功率≥99.9% | 产品 + SRE |
| 错误预算 | Error Budget | 1 − SLO 允许的失败额度 | 由 SLO 推导 |
举例:SLO 设”月度 API 成功率 ≥ 99.9%”,那么整月允许的错误比例就是 0.1%,这就是错误预算。预算花太快,说明系统不稳,应暂停feature投入、转去还技术债;预算充裕,则可以大胆发布。
四、动手定义 SLO:以 API 可用性为例
以”订单查询接口”为例,用 Prometheus 记录成功率。先在应用侧暴露请求计数与失败计数,再用 Recording Rule 预聚合 SLI:
# prometheus/recording_rules.yml
groups:
- name: slo_rules
rules:
# 近 5 分钟订单查询成功率(SLI)
- record: job:order_query:success_ratio_5m
expr: |
sum(rate(http_requests_total{job="order",code!~"5.."}[5m]))
/
sum(rate(http_requests_total{job="order"}[5m]))
接着把 SLO 表达成”坏事件比率不超过 0.1%”,并用多窗口、多燃烧率(burn rate)的告警防止瞬态抖动误报:
# 燃烧率 = 实际错误率 / 预算允许错误率
# 1h 窗口燃烧率 > 14.4(即 1h 烧完 2% 预算)触发 Page
- alert: OrderQueryErrorBudgetBurnFast
expr: |
(
sum(rate(http_requests_total{job="order",code=~"5.."}[1h]))
/
sum(rate(http_requests_total{job="order"}[1h]))
) > (0.001 * 14.4)
for: 2m
labels:
severity: page
annotations:
summary: "订单查询错误预算快速燃烧"
这类告警规则的具体编写套路,我们在 Prometheus 告警规则实战 里已经展开过 Recording Rule 与 Alertmanager 路由,这里直接复用其多窗口燃烧率范式即可。
五、错误预算怎么花:用发布换稳定
错误预算最被低估的用法,是把它变成发布闸门。常见实践是:
- 预算充足(如过去 28 天仅用掉 10%):可正常灰度发布,甚至放开实验性 feature。
- 预算告急(用掉 50% 以上):冻结非必要变更,把容量、重试、降级提上日程。
- 预算耗尽:暂停一切新功能,进入”可靠性冻结期”,直到预算回血。
这把”可靠性”从口号变成了工程排期的硬约束,也避免了”一边救火一边上新”的恶性循环。配合 Prometheus + Grafana 监控面板,错误预算进度条可以实时挂在值班大屏上。
六、把 OOD 落进日常:评审清单
要让 OOD 不沦为文档,关键是在研发流程里植入三个检查点:
- 设计评审:新接口必须写明核心 SLI 与 SLO,写不出的需求打回。
- 代码评审:是否带了关键路径的埋点?失败路径有没有日志和指标?
- 发布评审:当前错误预算是否允许这次变更?
下面这段 OpenTelemetry 片段,就是”代码评审”阶段该检查的最小可观测性投入——给关键 Span 打上业务属性:
from opentelemetry import trace
tracer = trace.get_tracer("order-service")
with tracer.start_as_current_span("order.query") as span:
span.set_attribute("order.id", order_id)
span.set_attribute("user.tier", user_tier) # 区分付费/免费用户影响
try:
result = repository.find(order_id)
span.set_attribute("order.found", True)
except Exception as e:
span.record_exception(e)
span.set_status(trace.Status(trace.StatusCode.ERROR, str(e)))
raise
七、三个常见反模式
落地 OOD 时最容易踩的坑,总结成下表对照:
| 反模式 | 表现 | 纠正 |
| 虚荣指标 | 盯 CPU、QPS 等底层指标 | 改为用户可感知的 SLI |
| 100% 可用 | SLO 设成 100%,永不达标 | 留出错误预算,接受不完美 |
| 告警无门 | 触发了却没人处理 | 绑定错误预算与 on-call |
八、落地路线建议
建议从一条核心链路起步,而不是全站铺开:先给营收相关接口定义 SLO,接上 Prometheus 与 OpenTelemetry,跑满一个迭代周期再看错误预算消耗曲线。当团队开始用”预算还剩多少”来讨论排期时,OOD 才算真正落地。容器化部署的服务可直接复用 Docker 容器化 的观测接入经验,把采集 agent 一并打进镜像。
九、三个团队落地 OOD 的真实节奏
不同成熟度的团队,落地 OOD 的切入点差异很大。创业早期团队往往监控近乎空白,正确做法是先选一条营收链路,把成功率、P99 延迟两个 SLI 接上,跑通”定义—采集—告警”的最小闭环,而不是一口气铺满全站几百个接口。
中大型团队的常见卡点不是工具,而是组织:SLO 由谁拍板、错误预算耗尽谁来叫停发布。这时要把 SLO 评审嵌进已有的需求与发布流程,让产品同学对”可用性目标”签字,研发对”埋点是否到位”签字。当错误预算第一次真正冻结了一次上线,OOD 才算从文档走进了工程文化。
可观测性驱动开发不是又一套工具,而是一种把”可靠性可度量”写进习惯的工程文化。先定 SLO,再谈埋点,最后用错误预算倒逼排期——当你能用数字回答”我们的系统到底稳不稳”时,运维深夜的电话自然会少下来。




