可持续性测试
1)基本概念和目标
可靠性(reliability)-运行概率;弹性(resilience)-故障发生时和之后的行为。
SLO/预算错误:降级的"可接受性"标准。
Steady-state hypothesis:对稳定指标的正式期望(例如p95 <200 ms,error rate <0。5%).如果假设成立,该实验被认为是成功的。
故障类型:网络(潜伏期、丢失/双重、断裂)、计算(CPU,内存)、擦伤(I/O,磁盘耗尽)、依赖项(5 xx, timeouts, rate-limit),逻辑(部分事件,"缓慢退化")、操作(发布,config)、深色(split)-brain,每小时轮班)。
2)可持续性金字塔
1.单位逻辑故障测试(retrai,等效性,taymout)。
2.分配有故障插入适配器(Testcontainers/tc-netem)。
3.具有网络/DB/缓存和 real-world配置文件的集成/系统。
4.在runbook'am上进行预测前的混沌实验(然后限制销售)。
5.Game dey是团队的脚本演习(人员+工具)。
3)可观察性作为基础
SLI:潜伏性p50/p95/p99, error rate, saturation (CPU/heap/FD/IOPS), drop/timeout, queue depth。
跟踪:查找故障下的"瓶颈"。
语义可持续性指标:成功的分数分数,shed请求分数,自我修复率(MTTR)。
实验标记:'chaos。experiment_id',"phase=inject/recover"在事件/逻辑中。
4)故障注射目录(faults)
网络:延迟/挤压,丢失/复制/重建,吞吐量限制,批量"风暴",TLS悬崖。
主机:CPU限制,泄漏/内存限制,GC暂停,句柄用尽,"clock skew"。
存储:潜伏期增长,EROFS,ENOSPC,复制副本退化,领导者损失。
相关性:5xx/429、减速、DNS翻转、过时证书、限额、"部分响应"。
数据:记录损坏,线程中的"漏洞",事件配对,版本冲突。
操作:发行失败,幻灯片标记,config漂移,手动错误(在模拟中)。
5)可持续性模式(要检查)
每个RPC上带有抖动和taymauts的复制品。
电路断路器(开口/半开口,指数恢复)。
Bulkheads(将池/队列隔离到关键域)。
负载共享(饱和时重置低优先级查询)。
Backpressure(链上信号,并发限制)。
Idempotency("副作用"上的幂等键)。
在来源退化的情况下进行积压和稳定。
Graceful Degradation(轻量级响应,stale数据,禁用图片)。
Timeout-budget(呼叫链上的总时间预算)。
原子/补偿(Saga/Outbox/Transactional Inbox)。
定额和复制(R/W定额,为了可用性而降级一致性)。
反entropy/反射(事件的"漏洞"中恢复)。
6)注射和期望处方(伪代码)
Retray with jitter和breaker
for attempt in 1..N:
if breaker. open(): return fallback()
res = call(dep, timeout = base 0. 8)
if res. ok: return res sleep(exp_backoff(attempt) jitter(0. 5..1. 5))
if attempt == N: breaker. trip()
return fallback()
Shading and Backpresher
if queue. depth() > HIGH cpu. load() > 0. 85:
if request. priority < HIGH: return 503_SHED limiter. acquire () # constrain concurrency
相似性
key = hash("payout:"+external_id)
if store. exists(key): return store. get(key)
result = do_side_effect()
store. put(key, result, ttl=30d)
return result
7)实验: 情景和假设
7.1"缓慢成瘾"
注射:+400 ms p95到外部API。
预期:Taymauts的增长≤ X%,打开断路器,后退响应,保留p99服务<SLA,在后退时没有级联。
7.2"部分缓存丢失"
注射:50%的Redis/Kesh Shard节点故障。
等待:小姐增加,但没有雪崩到源头(请求coalescing/immutable TTL),自动加热和恢复。
7.3 "DB中的Split-brain"
注射:失去领导者,切换到副本。
等待:短暂的录音,从法定人数中读取,没有数据丢失,Outbox不会丢失消息。
7.4 "ENOSPC/磁盘已满"
注射:95-100%的磁盘。
等待:紧急日志轮换,非锁相故障,关键日志保存(WAL),Alerta和自动移动。
7.5"交通风暴"
注射:× 3个RPS到10分钟的热末端。
等待:低优先权着色、"核"轨道稳定的p95、限制内队列增长、缺乏DLQ风暴。
7.6 «Clock Skew»
注射:将noda时间移至+/− 2分钟。
等待:正确的TTL/签名(leeway),后台的单调计时器,允许漂移时的有效令牌。
8)实验环境与安全
从pre-prod开始,合成数据尽可能接近configa/拓扑的销售。
在销售中-仅受控窗口,幻灯片,回合振幅,自动回滚和"红色按钮"。
Guardrails:RPS限制/错误,SLO警卫,在严重事件中阻止发布。
强制性的运行手册:如何回滚,打电话给谁,在哪里观看。
9)自动化和CI/CD
实验目录作为代码(YAML/DSL):目标,注入,度量,阈值,回滚的"按钮"。
每个版本中的烟雾混乱:在牛排中短暂注射(例如2分钟+200毫秒成瘾)。
夜间矩阵运行:服务×故障类型。
释放门:如果稳定性低于阈值(例如"慢依赖性"下的'fallback coverage <95%'),则禁止丢弃。
10)数据和一致性
检查补偿(Saga):部分完成的操作必须达到商定的状态。
测试事件的重播/配对、订单交付、"孔"和继电器。
验证失败后的域不变量:平衡不是负的,事务不会"卡住",限制不会中断。
11)反模式
仅测试快感路径和无故障负载。
没有jitter的retrai →一场退化风暴。
缺乏全球时间预算→级联时间预算。
所有任务的单个池→无隔离(bulkheads)。
"无限"队列→ 潜伏期/OOM的增长。
实验的零遥测→"盲目"混沌实践。
销售溷乱,没有回滚/限制/负责任的所有者。
12)建筑师支票清单
1.是否定义了阶梯状态假设和SLO?
2.每个RPC上都有taymouts,带挤压器的转发,破发器?
3.实现了牛头、限量版、背压式、装载式剪裁?
4.缓存是稳定的:coalescing,缓存风暴保护,加热?
5.Outbox/Saga的副作用,等效键?
6.法定人数/复制/传送器是否经过测试?
7.CI/CD中有实验目录,夜间混乱和大门?
8.度量/跟踪标记实验,有行车记录吗?
9.Runbook'和'红色按钮'准备就绪,责任已经指定?
10.定期与Dev/SRE/Support一起玩游戏?
13)迷你工具和脚本示例(YAML草图)
网络(tc/netem)
yaml experiment: add-latency target: svc:payments inject:
netem:
delay_ms: 300 jitter_ms: 50 loss: 2%
duration: 10m guardrails:
error_rate: "< 1%"
p95_latency: "< 400ms"
CPU/Heap
yaml inject:
cpu_burn: { cores: 2, duration: 5m }
heap_fill: { mb: 512 }
依赖性
yaml inject:
dependency:
name: currency-api mode: slow p95_add_ms: 500 fallback_expectation: "serve stale rates ≤ 15m old"
结论
可持续性测试不是"溷乱的把戏",而是使系统在故障下可预测的纪律。清晰的假设,遥测,受控实验目录以及嵌入到模式体系结构中(定时器,断路器,绝缘,等效性),将潜在事件转化为受控场景。该团队对发布有信心,即使处于故障状态,用户也能获得稳定的服务。