周五下午三点发版,六点出事。值班表上只有一个人,他在群里问"谁改过这个配置",没人回答;数据库回滚文档写着"联系 DBA",而 DBA 周末不在线。
事后总结写成"周五不要发版"。这条规则会被记住三个月,然后被一次紧急需求打破。真正的原因不是周五,而是发布能力与响应能力不匹配:发得出,但接不住。
1. 窗口是两种能力的匹配,不是时间表
| 判断维度 | 看什么 | 变差时窗口应收窄 |
|---|---|---|
| 发布能力 | 变更的可逆性、自动化程度、验证手段 | 需要人工介入才能回退 |
| 响应能力 | 当时能调动的人力、熟悉度、依赖支持 | 值班人数少、支持窗口外 |
| 影响面 | 受影响用户比例、是否涉及数据 | 不可逆的数据变更 |
窗口的作用不是限制发布,而是让发布风险与当时的接住能力对齐:同一个服务,周二上午十点可发,周六凌晨三点不可发,差别不在代码。
2. 三类窗口与判定依据
| 窗口 | 判定依据 | 典型形态 |
|---|---|---|
| 自由发布 | 风险低且可逆,响应能力充足 | 工作日白天、值班满编 |
| 有条件发布 | 风险中或响应能力偏低 | 需值班人确认、限定变更类型 |
| 禁止发布 | 风险高且响应能力不足 | 冻结期、节假日、值班单点 |
判定是二维的:变更风险 × 当时响应能力。两维都要能写出来,否则规则会退化成"领导在就能发"。
─── 窗口判定(占位,二维查表,不靠记忆)
响应能力充足 响应能力不足
风险低 自由发布 有条件发布(需值班人确认)
风险中 有条件发布 禁止发布
风险高 禁止发布 禁止发布
判定输入: 可逆性 / 影响面 / 是否改数据 / 当时在线人数与外部支持
3. 响应能力的四个变量
| 变量 | 可判定的信号 | 缺失时的表现 |
|---|---|---|
| 值班人数 | 同一时间在线人数、是否单点 | 出事时无人复核,靠一个人猜 |
| 熟悉度 | 近 30 天是否处理过该服务故障、是否读过手册 | 拿着手册也不知从哪下手 |
| 外部依赖可用性 | 第三方支持窗口、云厂商状态 | 卡在等对方响应 |
| 可观测性完好度 | 关键面板与告警是否在线、能否区分新旧版本 | 分不清是这次发布还是别的原因 |
熟悉度最容易被高估:值班表上的名字不等于能力。判断方式是上次该服务出事时是不是同一个人处理的——如果每次都是他,他休假时窗口实质上就是禁止发布。
─── 发版前响应能力自检(占位,五项全过才自由发布)
1 在线人数 ≥ 2(含能回滚的那个人)?
2 本次变更需要人工介入吗?需要谁?
3 外部依赖在这段时间有人响应吗?
4 面板与告警能区分新旧版本吗?
5 回滚动作被独立演练过一次吗?
4. "周五不发"的真实理由与它的过度泛化
| 原始理由 | 什么条件下成立 | 什么条件下失效 |
|---|---|---|
| 恢复依赖人工 | 回滚需人判断、手动执行 | 全自动检测与回滚 |
| 外部支持下班 | 依赖第三方排障 | 依赖自持、无外部支持需求 |
| 影响被放大 | 用户集中使用、支持不在线 | 内部服务、无外部用户 |
| 值班单点 | 一人值班且未休息 | 值班满编或响应非人 |
被记住的往往是结论,而理由是条件。规则要写清前提,前提不成立时允许发,否则它会在第一次紧急发布时被整体抛弃。
5. 窗口与业务峰谷
| 业务类型 | 真实峰值 | 合适的发布时段 |
|---|---|---|
| 电商/交易 | 晚间与促销节点 | 凌晨到早晨,避开促销预热 |
| 海外用户占比高 | 按用户时区 | 用户低谷、且自家 oncall 在线 |
| 内部工具 | 工作日白天 | 白天(有人用才能发现异常) |
| 批处理/数据链路 | 夜间批处理 | 批处理结束后的早晨 |
把窗口等同于上班时间是常见错位:内部工具的白天是高峰,安静窗口反而是晚上——但那时没人用、没人报错。 窗口要与可观测、可响应对齐。
6. 跨时区
| 策略 | 做法 | 代价 |
|---|---|---|
| 跟随开发时区 | 团队白天发 | 用户高峰期发布,影响面大 |
| 跟随用户时区 | 用户低谷发 | 开发团队在深夜待命 |
| 跟随 oncall 时区 | 谁值班谁定 | 响应者与决策者可能不同时区 |
第三种最容易出现空心观测窗:宣布"观察两小时",而决策者已入睡,出事时没人有权判断要不要回滚。跨时区发布至少要有一条成立:接管权明确授予当地值班人,或观测窗与决策者在线时间重合。
7. 积压与解禁首日
| 现象 | 成因 | 风险 |
|---|---|---|
| 解禁首日集中发布 | 冻结期攒下的变更一次性上线 | 因果无法区分,回滚互相干扰 |
| 积压后放宽标准 | 团队想"补回来" | 高风险变更挤进低风险窗口 |
| 窗口内发布占比虚高 | 变更被拆成多次小发布 | 指标好看,暴露面未变 |
解禁首日是全年最危险的一天,因为多个变更共享同一个失败归因空间。缓解手段是把解禁首日当作一个独立窗口来管理。
─── 解禁首日规则(占位)
- 首日只放低风险、可逆变更,且单人单次只发一项
- 高风险变更分散到解禁后第 3 个工作日之后
- 观测窗按平常的 1.5 倍,值班人数不减
- 首日事故按"窗口设计问题"单独回溯一次
8. 例外通道与它的审批成本
| 例外情形 | 需要的证据 | 批准人 |
|---|---|---|
| 影响用户的紧急修复 | 回滚方案、响应人具名、影响面说明 | 业务 + 运维双签 |
| 安全与合规补丁 | 不可延迟的理由 | 运维 + 安全 |
| 冻结期必须上线的商业承诺 | 商业决策书面确认 | 业务负责人署名 |
例外通道的审批成本必须可感知:免签的例外等于没有窗口。成本不来自签字本身,而来自你必须当场写出回滚方案与响应人——这两项才是把关的东西。
─── 例外单(占位,事后进窗口复盘)
exception: EXC_2311
window_rule_violated: "周五 18:00 后禁止发布"
reason: "支付回调异常,影响下单"
rollback: "配置回退,已验证过一次"
responder: ROLE_ONCALL // 具名,不是"值班群"
approvers: [ROLE_BUSINESS, ROLE_OPS]
aftermath: 结果与用时,进下一次规则修订
9. 窗口应该由谁定
| 归属 | 倾向 | 后果 |
|---|---|---|
| 业务方 | 宽松,尽快上线 | 风险外溢给值班人 |
| 运维方 | 保守,减少事故 | 积压增加,业务绕过规则 |
| 团队自定 | 贴近实际能力 | 跨团队不一致,难以协调 |
可行做法是团队提出 + 运维与业务共同确认:团队知道自己的响应能力,运维知道跨服务影响,业务知道不可延迟的节点。规则还要能被数据修订——没有修订机制的窗口规则,三年后限制的仍然是三年前的业务形态。
10. 量化依据:从历史事故的时间分布取数
| 口径 | 正确写法 | 常见陷阱 |
|---|---|---|
| 分母 | 每次发布的事故率 | 只看事故总数,忽略发布次数差异 |
| 样本 | 近一年同类变更 | 样本太少时不下结论 |
| 归因 | 按变更类型分组 | 把所有事故混成一类 |
| 时点 | 按小时与星期分布 | 只按工作日/周末二分 |
分母问题最常见:窗口外发布本来就少,事故数自然少,结论会自证。要用每次发布的事故率,而不是事故数量。
─── 取数骨架(占位,字段按你们的变更平台核对)
─── 变更记录: id, deploy_type, started_at, rolled_back, incident_id
─── 事故记录: incident_id, detected_at, impact, root_cause
─── 分组: 按 started_at 的小时与星期聚合,算每次发布的事故率
─── 输出: 样本不足的格子标注 n 值
11. 度量:五个能改变决策的数
| 指标 | 口径 | 用来决定什么 |
|---|---|---|
| 窗口内发布占比 | 窗口内发布 / 总发布 | 规则是被遵守还是被绕过 |
| 非窗口发布事故率 | 每次非窗口发布的事故率 | 窗口限制是否真的有效 |
| 积压量 | 冻结期结束时的待发变更数 | 首日是否需要额外限制 |
| 解禁首日事故率 | 该日每次发布的事故率 | 是否需要更细的分批规则 |
| 例外单数量与结果 | 例外中事后产生事故的比例 | 例外是否被滥用 |
第二项与第五项是唯一能验证规则合理性的数据;其余三项只用来决定规则要不要调。
12. 排错:窗口规则失效的六种现场
| 现象 | 真实成因 | 处理方向 |
|---|---|---|
| 规则只在有人盯时执行 | 判定依赖人而非查表 | 把二维判定写成可查规则 |
| 例外越来越多 | 审批成本接近零 | 例外单必须写回滚与响应人 |
| 周五总在破例 | 规则未写成立条件 | 写明前提,前提外允许发 |
| 解禁后连着出事 | 积压一次性释放 | 首日限单,分散高风险项 |
| 指标说窗口有效 | 分母用错,自证结论 | 改用每次发布的事故率 |
| 值班人反对无效 | 窗口由业务单方决定 | 改为团队提案 + 双签 |
13. 边界:硬窗口收益被抵消的情况
| 场景 | 为什么收益低 | 替代约束 |
|---|---|---|
| 一天多次发布的高频团队 | 窗口粒度失去意义 | 用变更分级 + 自动门禁替代 |
| 无状态且可秒回滚的服务 | 接不住的概率极低 | 只保留"冻结期"这一档 |
| 全自动金丝雀与自动回滚 | 恢复不依赖人的在线时间 | 用观察指标与自动阈值替代窗口 |
| 单人团队 | 没有第二个人可以等 | 用"只在清醒时段发"替代固定窗口 |
| 无外部用户 | 影响面与支持窗口都不存在 | 只需要避开自己的批处理时段 |
判断口径:窗口的收益来自"这段时间出问题时,接住它的能力更差"。 当恢复已经自动化,或发布频次高到窗口无法表达风险差异时,时段限制带来的只是积压与破例。
14. 自测
- 为什么说发布窗口是"发布能力与响应能力的匹配"?
- 判定三类窗口的两个维度分别是什么?
- "周五不发"在什么前提下成立,在什么前提下失效?
- 为什么解禁首日是风险最高的一天?
- 用"事故数量"评估窗口有效性,错在哪里?
- 什么情况下硬窗口的收益被完全抵消?