监控观察期法

3 min read
Zekari
系统设计监控生产环境运维可靠性工程

部署完成,问题才刚开始

修复完成。代码提交。CI通过。部署成功。

大多数人在这里停下了。认为任务完成。

但真正的问题是:修复真的有效吗?

本地测试通过不代表生产环境没问题。CI检查通过不代表用户不会遇到错误。部署成功不代表业务指标改善。

修复只是假设。监控才是验证。

💡 Click the maximize icon to view in fullscreen

观察期的本质

观察期不是被动等待。是主动验证。

每个修复都基于某个假设:

  • 修复了402错误 → 假设:用户不会再看到不正确的402响应
  • 加强了输入验证 → 假设:恶意输入会被拦截
  • 实现了防重复提交 → 假设:并发扣费问题会减少

这些假设需要数据证明。

观察期的核心是:为每个假设设定可验证的指标

如果假设是"402错误率应该下降",就监控402响应数。如果假设是"XSS攻击被拦截",就监控安全事件日志。如果假设是"重复提交减少",就对比修复前后的重复率。

没有指标的假设,就是盲目的乐观。

监控的三个维度

监控不是看一个数字。是看多个维度的变化。

1. 错误率维度

修复的直接目标。402错误应该减少。500错误应该因正确的配置错误处理而出现(这是好事,说明系统能识别配置问题)。

// 查询最近1小时的402错误任务
SELECT
  id,
  user_id,
  model,
  status,
  error_message,
  created_at
FROM ai_generations
WHERE created_at > NOW() - INTERVAL '1 hour'
  AND status = 'failed'
  AND error_message LIKE '%402%'
ORDER BY created_at DESC;

不仅看总数,还要看分布。是集中在某个用户?某个模型?某个时间段?

2. 安全维度

防御性措施是否生效。恶意输入是否被拦截。大文件上传是否被阻止。

# 查找被拦截的恶意prompt
wrangler tail api-gateway --format pretty | grep "Blocked potentially malicious prompt"

# 查找图片验证失败
wrangler tail api-gateway --format pretty | grep "Blocked invalid image"

这个维度的指标很特殊:有时候没有日志才是好消息。如果没有恶意攻击,就不会有拦截日志。但如果有拦截日志,说明防御措施在工作。

3. 业务维度

最终目标不是减少错误,而是改善业务指标。视频生成成功率应该提升。用户体验应该改善。

-- 最近24小时视频生成成功率
SELECT
  COUNT(*) FILTER (WHERE status = 'completed') as completed_count,
  COUNT(*) FILTER (WHERE status IN ('failed', 'failed_processing')) as failed_count,
  COUNT(*) as total_count,
  ROUND(100.0 * COUNT(*) FILTER (WHERE status = 'completed') / COUNT(*), 2) as success_rate
FROM ai_generations
WHERE created_at > NOW() - INTERVAL '24 hours'
  AND type = 'video';

如果错误率下降了,但成功率没提升,说明修复可能不够彻底。

监控不只是收集数据,而是对比数据与预期。

每个修复都应该有明确的预期改善:

  • 402错误误报率应该 < 0.1%
  • XSS攻击拦截率应该 = 100%
  • 重复提交率应该减少 > 80%

没有预期,就无法判断修复是否成功。即使错误率从10%降到5%,如果预期是降到1%,这个修复仍然不够。

预期来自对问题的理解。如果问题是"配置错误导致402",预期应该是"配置错误返回500,402仅在积分不足时出现"。如果问题是"防重复提交",预期应该基于对并发场景的分析。

分阶段检查清单

48小时观察期,分三个检查点。

部署后1小时:快速验证

修复是否正常工作。基本功能是否可用。有没有明显的回归问题。

检查项:

  • 部署状态确认(Worker版本、环境变量)
  • 首次错误日志扫描(是否有新的异常)
  • 核心功能冒烟测试(手动触发一次正常流程)
  • 告警系统测试(Telegram通知是否能收到)

这个阶段不是找所有问题,而是确认"没有重大灾难"。

部署后24小时:趋势观察

数据开始有意义。可以看到初步的趋势。

检查项:

  • 错误率对比(与修复前同期对比)
  • 用户分布分析(是否集中在特定用户)
  • 业务指标初步对比(成功率、转化率)
  • 异常模式识别(是否有新的错误类型)

这个阶段是发现问题的关键窗口。如果修复无效,通常在24小时内会显现。

部署后48小时:最终评估

数据足够完整。可以做出结论。

检查项:

  • 完整数据汇总(所有维度的指标)
  • 预期目标达成评估(是否达到预期改善)
  • 修复有效性结论(是否需要进一步优化)
  • 后续行动决策(是否需要新的修复迭代)

48小时不是随意选择的。太短,数据不够;太长,反馈太慢。对于大多数Web服务,48小时足够覆盖用户的主要使用场景。

观察期的长度取决于系统的特性:

高频交易系统:可能只需要1-2小时。交易量大,数据快速积累,问题快速暴露。

企业SaaS系统:可能需要1周。用户主要在工作日使用,需要覆盖完整的工作周。

视频生成服务(本文场景):48小时合适。用户使用分布相对均匀,48小时能覆盖两个完整的24小时周期,包含高峰和低谷。

关键不是具体的时长,而是确保观察期能捕捉到系统的典型使用模式。

应急响应的预设

观察期不只是观察。也是准备。

如果监控发现问题,应该如何响应?提前规划,而不是临时决策。

场景1:错误率突增(>5%)

症状:Cloudflare Analytics显示402或500响应数激增

响应步骤:

  1. 立即排查(5分钟内)- 查看实时日志,识别错误模式
  2. 临时缓解(15分钟内)- 如果是特定模型,禁用该模型;如果是配置问题,修复配置
  3. 根因分析(1小时内)- 深入日志,理解为什么修复无效
  4. 修复部署(根据情况)- 准备hotfix或配置更新

场景2:告警过多(>10次/小时)

症状:Telegram群组频繁收到告警

响应步骤:

  1. 确认真实性 - 是真实问题还是告警配置过于敏感
  2. 修复配置 - 如果是模型配置缺失,更新pricing
  3. 调整告警 - 如果是告警阈值问题,调整阈值

场景3:性能下降(P95 > 2000ms)

症状:响应时间显著增加

响应步骤:

  1. 检查瓶颈 - 数据库、外部API、还是Worker自身
  2. 临时优化 - 增加超时、减少日志、降级服务
  3. 长期规划 - 实施缓存、优化查询、架构调整

预设响应计划的价值在于:减少决策时间,增加响应速度

当问题发生时,你不是在想"该怎么办",而是在执行"已经计划好的步骤"。

相关阅读:错误隔离讨论了如何设计系统使单个组件失败不会级联;让错误浮现强调了不掩盖问题的重要性。

监控的哲学

监控不是为了证明"我们做对了"。是为了发现"我们做错了什么"。

修复代码时,我们做出了很多假设:

  • 假设问题的根因被正确识别
  • 假设解决方案能解决问题
  • 假设没有引入新的问题

监控是在系统性地验证这些假设。

有些团队把监控当作形式。部署完看一眼日志,没有明显错误就收工。这不是监控,是自我安慰。

真正的监控是:

  • 主动寻找问题,而不是被动等待问题出现
  • 对比预期与现实,而不是只看绝对数字
  • 持续验证假设,而不是一次性检查

每个指标都在回答一个问题:修复是否真的解决了问题?

如果答案是"是",观察期结束,任务完成。

如果答案是"否",观察期提供了足够的数据,告诉你下一步该如何改进。

监控能发现很多问题,但不能发现所有问题。

监控无法发现的:

  • 低频但高影响的边缘案例(可能数月才出现一次)
  • 用户体验的细微下降(数据正常,但感知变差)
  • 潜在的安全漏洞(在被攻击前不会触发)

监控是安全网,不是全部保障。

完整的质量保证需要:

  • 代码审查(防御性编程
  • 测试覆盖(单元测试、集成测试、端到端测试)
  • 监控观察(本文主题)
  • 用户反馈(支持工单、用户调研)

监控只是其中一环,但它是验证修复效果最直接的一环。

数据驱动的修复迭代

修复不是一次性的。是迭代的。

第一次修复可能解决了80%的问题。监控发现还有20%的边缘案例。第二次修复针对这20%。监控再次验证。

这个循环持续,直到:

  • 所有预期目标达成
  • 边际收益递减(继续优化的投入产出比过低)
  • 新的更高优先级问题出现

监控提供反馈,反馈驱动改进。

没有监控,修复是盲目的。你不知道问题是否解决,不知道引入了什么新问题,不知道下一步该优化什么。

有了监控,修复是科学的。数据告诉你哪里好,哪里差,哪里需要关注。

最后

部署不是终点。是验证的起点。

修复代码时,我们在纸上画出了解决方案。监控观察期,让这个方案在真实世界中接受检验。

48小时,三个检查点,多个维度的指标。不是为了完美,而是为了真实。

真实的数据,真实的反馈,真实的改进。

监控观察期不是额外的工作,而是修复流程的有机组成部分。没有监控的修复,就像没有测试的代码,看起来完成了,但谁也不知道它是否真的有效。

让数据证明修复。这是对用户负责,也是对自己负责。

Related Posts

Articles you might also find interesting

管理后台需要两次设计

3 min read

第一次设计回答"发生了什么",第二次设计回答"我能做什么"。在第一次就试图解决所有问题,结果是功能很多但都不够深入。

系统设计API 设计
Read More

告警分级与响应时间

2 min read

不是所有问题都需要立即响应。RPC失败会在凌晨3点叫醒人。安全事件每15分钟检查一次。支付成功只记录,不告警。系统的响应时间应该匹配问题的紧急程度。

系统设计监控
Read More

配置不会自动同步

2 min read

视频生成任务永远pending,代码完美部署,队列正确配置。问题不在代码,在于配置的独立性被低估。静默失败比错误更危险。

部署配置管理
Read More

双重验证:Stripe生产模式的防御性切换

7 min read

从测试到生产不是更换API keys,而是建立一套双重验证系统。每一步都在两个环境中验证,确保真实支付不会因假设而失败。

系统设计Stripe
Read More

错误隔离

3 min read

失败是必然的。真正的问题不是失败本身,而是失败如何蔓延。错误隔离不是为了消除失败,而是为了控制失败的范围。

系统设计可靠性工程
Read More

单例模式管理 Redis 连接

5 min read

连接不是技术细节,而是系统与外部世界的第一次握手,是可靠性的起点

系统设计后端架构
Read More

监听 Redis 连接事件 - 让不可见的脆弱变得可见

4 min read

连接看起来应该是透明的。但当它断开时,你才意识到透明不等于可靠。监听不是多余,而是对脆弱性的承认。

系统设计Redis
Read More

What Monitoring Systems See

7 min read

Production logs showed errors everywhere. But most weren't errors at all. When test webhooks generate error-level logs, and successful validations leak customer emails, the monitoring system loses its ability to tell you what's actually wrong.

日志监控
Read More

指数退避超时 - 防止无限重试循环

3 min read

失败后立即重试是本能。但有些失败,需要时间来消化。指数退避不是逃避失败,而是尊重失败。

系统设计可靠性工程
Read More

幂等性检查

1 min read

在不确定的系统中,幂等性检查是对重复的容忍,是对稳定性的追求,也是对失败的预期与接纳

系统设计分布式系统
Read More

文档标准是成本计算的前提

3 min read

API文档不只是写给开发者看的。它定义了系统的边界、成本结构和可维护性。统一的文档标准让隐性成本变得可见。

API文档
Read More

BullMQ 队列

3 min read

队列不是技术选型,而是对时间的承认,对顺序的尊重,对不确定性的应对

系统设计异步处理
Read More

BullMQ Worker

2 min read

Worker 的本质是对时间的重新分配,是对主线的解放,也是对专注的追求

系统设计异步处理
Read More

CRUD 操作

2 min read

四个字母背后,是数据的生命周期,是权限的边界,也是系统设计的基础逻辑

系统设计软件工程
Read More

数据库参数国际化:从 13 个迁移学到的设计原则

3 min read

数据不该懂语言。当数据库参数嵌入中文标签时,系统的边界就被语言限制了。这篇文章从 13 个参数对齐迁移中提炼出设计原则——国际化不是功能,是系统设计的底层约束。

数据库国际化
Read More

Stripe Webhook中的防御性编程

2 min read

三个Bug揭示的真相:假设是代码中最危险的东西。API返回类型、环境配置、变量作用域——每个看似合理的假设都可能导致客户损失。

Web开发系统设计
Read More

在运行的系统上生长新功能

3 min read

扩展不是推倒重来,而是理解边界,找到生长点。管理层作为观察者和调节器,附着在核心系统上,监测它,影响它,但不改变它的运行逻辑。

系统设计架构
Read More

实现幂等性处理,忽略已处理的任务

3 min read

在代码层面识别和忽略已处理的任务,不是简单的布尔检查,而是对时序、并发和状态的深刻理解

系统设计并发控制
Read More

缺失值的级联效应

3 min read

一个NULL值如何在调用链中传播,最终导致错误的错误消息。理解防御层的设计,在失败传播前拦截。

系统设计防御性编程
Read More

Props Drilling

3 min read

数据在组件树中层层传递,每一层都不需要它,却必须经手。这不是技术债,是架构对真实需求的误解。

React组件设计
Read More

队列生产者实例的工厂函数

4 min read

工厂函数不是设计模式的炫技,而是对重复的拒绝,对集中管理的追求,对变化的准备

系统设计设计模式
Read More

资源不会消失,只会泄露

2 min read

在积分系统中,用户的钱不会凭空消失,但会因为两个时间窗口而泄露:并发请求之间的竞争,和回调永不到达的沉默。

系统设计并发控制
Read More

RPC函数的原子化处理

1 min read

当一个远程函数做太多事情,失败就变得难以理解

分布式系统RPC
Read More

RPC函数

2 min read

关于远程过程调用的本质思考:当你试图让远方看起来像眼前

分布式系统RPC
Read More

使用Secret Token验证回调请求的合法性

2 min read

在开放的网络中,信任不能被假设。Secret Token 是对身份的确认,对伪装的识别,也是对安全边界的坚守

Web 安全系统设计
Read More