name: qa-resilience description: “在设计或测试分布式系统韧性时使用:超时/截止时间、重试(退避 + 抖动、重试预算)、断路器、隔离舱、背压/负载削减、优雅降级、健康检查、混沌实验/游戏日/灾难恢复演练,以及基于SLO的可靠性门。”
QA韧性(2026年1月) - 故障模式测试与生产硬化
此技能提供执行就绪的模式,用于构建能够优雅处理故障的韧性、容错系统,并通过测试验证这些行为。
常见请求
在用户请求以下内容时使用此技能:
- 断路器实现
- 重试策略和指数退避
- 资源隔离的隔离舱模式
- 背压、负载削减和过载保护
- 外部依赖的超时策略
- 优雅降级和回退机制
- 健康检查设计(活跃性 vs 就绪性)
- 错误处理最佳实践
- 混沌工程设置
- 游戏日 / 灾难恢复 / 故障转移测试(带护栏)
- 生产硬化策略
- 故障注入测试
何时不使用此技能:
- 无外部依赖的简单CRUD应用 — 使用基本错误处理
- 单一数据库,无网络调用 — 标准连接池足够
- 纯批处理作业,手动重试 — 计划作业框架处理此问题
- 仅前端验证 — 参见software-frontend
快速开始(默认工作流)
如果缺少关键上下文,询问:关键用户旅程、依赖清单(包括第三方)、SLO/SLI目标、当前超时/重试/断路器设置、幂等性/去重策略,以及允许故障注入的位置(本地/预生产/生产)。
- 定义范围:关键用户旅程、前N个依赖和SLOs/SLIs(延迟、错误、饱和)。
- 为每个依赖构建依赖契约:超时预算、重试策略(有界 + 抖动)、幂等性/去重预期、断路器阈值和回退/降级行为。
- 选择测试框架:首先确定性故障注入(模拟/伪造、故障代理、服务网格故障),然后分阶段混沌实验,最后游戏日/灾难恢复演练(如适用)。
- 定义通过/失败信号:错误预算消耗、p95/p99预算、回退率、队列积压、断路器状态变化和恢复时间。
- 产出工件(使用模板):韧性测试计划模板、故障注入手册、韧性运行手册模板。
核心QA(默认)
故障模式测试(要验证的内容)
- 超时:每个网络调用和数据库查询都有有界超时;验证链式调用中的超时预算和截止时间/取消传播。
- 重试:有界重试,带退避 + 抖动;验证幂等性/去重和重试风暴保护(上限、预算和每次重试超时)。
- 依赖故障:部分中断、下游慢速、速率限制、DNS故障、身份验证故障和损坏/无效响应。
- 过载/饱和:连接池耗尽、队列积压、线程池饥饿和速率限制;验证背压和负载削减。
- 降级模式用户体验:依赖失败时用户看到/获得的内容(缓存/陈旧/部分响应)以及适用的一致性保证。
- 健康检查:验证活跃性/就绪性/启动探针行为(Kubernetes探针:https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/)。
适度混沌工程(安全构建)
- 定义稳态和假设(混沌工程原则:https://principlesofchaos.org/)。
- 从非生产环境开始;在生产环境中,使用最小爆炸半径、限时运行和明确的终止标准。
- 必需:回滚计划、所有者和运行实验前的可观测性信号。
- 必需(生产):变更窗口 + 值班人员知晓、错误预算健康,以及基于客户影响信号的明确停止条件。
负载/性能 + 生产护栏
- 负载测试验证容量和尾部延迟;韧性测试验证故障下的行为。
- 护栏:
- 按计划(每晚)和灰度部署运行重型韧性/性能套件,而不是每个PR。
- 基于回归预算(p99延迟、错误率、饱和)而非原始CPU/内存来门控发布。
韧性测试的稳定性控制
- 如果实验不是确定性的,混沌/故障注入可能看起来“不稳定”。
- 首先稳定实验:固定爆炸半径、受控故障参数、确定性持续时间、强可观测性。
调试人机工程学
- 每次韧性测试运行应捕获:实验参数、目标范围、时间戳和失败时的跟踪/日志链接。
- 倾向于使用跟踪/指标来确认故障是预期的(而非附带损害)。
做 / 避免
做:
- 显式测试降级模式;记录预期的用户体验和API响应。
- 在集成测试中使用故障注入验证重试/超时。
避免:
- 无界重试和缺失超时(放大事件)。
- 仅“快乐路径”测试,忽略下游故障类别。
快速参考
| 模式 | 机制 / 工具 | 何时使用 | 配置(起始点) |
|---|---|---|---|
| 断路器 | 应用级断路器或服务网格;发出断路器状态变化 | 持续下游故障或超时 | 在持续错误/超时率下开启;使用半开探针;根据流量 + 错误预算调整窗口 |
| 带退避的重试 | 客户端重试库;尊重429/503的Retry-After | 瞬态故障和速率限制 | 用户面向路径最多2-3次重试;退避 + 抖动;每次重试超时;永远不超过剩余截止时间 |
| 超时预算 | 截止时间/取消 + 数据库语句超时 | 任何远程调用或查询 | 每跳预算;快速失败;传播截止时间;设置数据库查询超时和池等待超时 |
| 隔离舱 + 背压 | 并发限制器、独立池/队列、准入控制 | 过载/饱和风险 | 为每个依赖设置独立池;限制队列;早期拒绝(429/503)而非未受控延迟增长 |
| 优雅降级 | 功能标志、缓存/陈旧回退、部分响应 | 非关键功能和部分中断 | 定义数据新鲜度 + 用户体验;仪器回退率;避免静默降级 |
| 健康检查 | K8s活跃性/就绪性/启动探针 | 编排和负载均衡 | 活跃性浅层;就绪性检查关键依赖(有界);启动用于慢初始化;添加优雅关闭 |
| 混沌 / 故障注入 | 故障代理、服务网格故障、托管混沌工具 | 验证真实故障模式下的行为 | 从非生产开始;控制爆炸半径;限时;预定义停止条件;记录实验参数 |
决策树:韧性模式选择
故障场景:[系统依赖类型]
├─ 外部API/服务?
│ ├─ 瞬态错误? → 重试带指数退避 + 抖动
│ ├─ 级联故障? → 断路器 + 回退
│ ├─ 速率限制? → 重试并尊重Retry-After头
│ └─ 慢响应? → 超时 + 断路器
│
├─ 数据库依赖?
│ ├─ 连接池耗尽? → 隔离舱隔离 + 超时
│ ├─ 查询超时? → 语句超时(5-10秒)
│ ├─ 副本延迟? → 从主节点回退读取
│ └─ 连接故障? → 重试 + 断路器
│
├─ 过载/饱和?
│ ├─ 队列/池增长? → 背压 + 限制队列 + 准入控制
│ ├─ 惊群效应? → 抖动 + 请求合并 + 缓存
│ └─ 昂贵路径? → 负载削减 + 功能标志降级
│
├─ 非关键功能?
│ ├─ 机器学习推荐? → 功能标志 + 默认值回退
│ ├─ 搜索服务? → 缓存结果或基本SQL回退
│ ├─ 电子邮件/通知? → 记录错误,不阻塞主流程
│ └─ 分析? → 即发即弃,断路器用于保护
│
├─ Kubernetes/编排?
│ ├─ 服务发现? → 活跃性 + 就绪性 + 启动探针
│ ├─ 慢启动? → 启动探针(failureThreshold: 30)
│ ├─ 负载均衡? → 就绪性探针(检查依赖)
│ └─ 自动重启? → 活跃性探针(简单检查)
│
└─ 测试韧性?
├─ 预生产? → 混沌工具箱实验
├─ 生产(低风险)? → 功能标志 + 灰度部署
├─ 计划测试? → 游戏日(季度)
└─ 持续混沌? → 低爆炸半径故障注入带强护栏
导航:核心韧性模式
-
断路器模式 - 防止级联故障
- 经典断路器实现(Node.js, Python)
- 调优、警报和回退策略
-
重试模式 - 处理瞬态故障
- 带抖动的指数退避
- 重试决策表(哪些错误要重试)
- 幂等性模式和Retry-After头
-
隔离舱隔离 - 资源分区
- 信号量模式用于线程/连接池
- 数据库连接池策略
- 基于队列的隔离舱带负载削减
-
超时策略 - 防止资源耗尽
- 连接、请求和空闲超时
- 数据库查询超时(PostgreSQL, MySQL)
- 链式操作的嵌套超时预算
-
优雅降级 - 保持部分功能
- 缓存回退策略
- 默认值和功能切换
- 使用Promise.allSettled的部分响应
-
健康检查模式 - 服务可用性监控
- 活跃性、就绪性和启动探针
- Kubernetes探针配置
- 浅层 vs 深度健康检查
导航:操作资源
导航:模板
-
韧性运行手册模板 - 服务硬化配置文件
- 依赖和SLOs
- 回退策略
- 回滚程序
-
故障注入手册 - 混沌测试脚本
- 成功信号
- 回滚标准
- 实验后复盘
-
韧性测试计划模板 - 故障模式测试计划(超时/重试/降级模式)
- 范围和依赖
- 故障矩阵和预期行为
- 可观测性信号和通过/失败标准
快速决策矩阵
| 场景 | 推荐 |
|---|---|
| 外部API调用 | 断路器 + 带指数退避的重试 |
| 数据库查询 | 超时 + 连接池 + 断路器 |
| 慢依赖 | 隔离舱隔离 + 超时 |
| 过载/饱和 | 隔离舱 + 背压 + 负载削减 |
| 非关键功能 | 功能标志 + 优雅降级 |
| Kubernetes部署 | 活跃性 + 就绪性 + 启动探针 |
| 测试韧性 | 混沌工程实验 |
| 瞬态故障 | 重试带指数退避 + 抖动 |
| 级联故障 | 断路器 + 隔离舱 |
要避免的反模式
- 无超时 - 无限等待耗尽资源
- 无限重试 - 放大问题(惊群效应)
- 重试无幂等性 - 重复副作用和数据损坏
- 无断路器 - 级联故障
- 紧耦合 - 一个故障破坏一切
- 静默故障 - 无降级状态的可观测性
- 无隔离舱 - 共享线程池耗尽所有资源
- 故障转移从未测试 - 真实事件中灾难恢复计划失败
- 仅测试快乐路径 - 生产中暴露故障
可选:AI / 自动化
做:
- 使用AI从明确风险注册表提出故障模式场景;仅保留映射到已知依赖和业务旅程的场景。
- 使用AI总结实验结果(指标增量、错误簇)和草拟事后时间线;用遥测验证。
避免:
- 无风险地图的“场景生成”(产生噪音和浪费负载)。
- 让AI放松超时/重试或移除护栏。
相关技能
- …/ops-devops-platform/SKILL.md — 事件响应、SLOs和平台运行手册
- …/software-backend/SKILL.md — API错误处理、重试和数据库可靠性模式
- …/software-architecture-design/SKILL.md — 系统分解和可靠性依赖设计
- …/qa-testing-strategy/SKILL.md — 回归、负载和故障注入测试策略
- …/software-security-appsec/SKILL.md — 安全故障模式和护栏
- …/qa-observability/SKILL.md — 指标、跟踪、日志和性能监控
- …/qa-debugging/SKILL.md — 生产调试和事件调查
- …/data-sql-optimization/SKILL.md — 数据库韧性、连接池和查询超时
- …/dev-api-design/SKILL.md — API设计模式包括错误处理和重试语义
使用说明
模式选择:
- 从外部依赖的断路器开始
- 为瞬态故障添加重试(网络、速率限制)
- 使用隔离舱防止资源耗尽
- 组合模式以实现深度防御
可观测性:
- 跟踪断路器状态变化
- 监控重试尝试和成功率
- 警报降级模式持续时间
- 测量故障后的恢复时间
测试:
- 从非生产开始混沌实验
- 在故障注入前定义假设
- 设置爆炸半径限制和自动回滚
- 记录学习成果和行动项
成功标准: 系统优雅处理故障、自动恢复、在中断期间保持部分功能,并快速失败以防止级联故障。韧性通过混沌工程主动测试。