没钱搞混沌工程?3个脚本教你低成本做故障演练

很多中小团队的技术负责人听到“混沌工程”这四个字,第一反应往往是:那是Netflix、阿里这些大厂才玩得起的高端玩具。我们连专职运维都没有,业务代码都写不完,搞什么破坏?

配图

我曾经也是这么想的。直到三年前的一个凌晨3点,我们的单体应用因为Redis抖动导致连接池爆满,整个系统雪崩。哪怕我重启了服务,因为大量请求瞬间涌入,系统又立马挂掉。我们就这样在“重启-崩溃-再重启”的死循环里折腾了两个小时,客户群里骂声一片。

那一刻我意识到:系统的脆弱性不会因为你团队小就放过你。相反,资源越少,越需要低成本的“疫苗”。

这就是我们这几年在只有5个开发、0个专职运维的情况下,摸索出的“土办法”混沌工程。不需要购买昂贵的SaaS服务,不需要复杂的Service Mesh,我们要的只是:让系统死得有尊严,活得更强硬。

别整虚的,先从“拔网线”开始

很多团队不敢做故障演练,是因为害怕“假戏真做”把生产环境搞挂了。我的建议非常直接:别一开始就在生产环境搞,去测试环境,但要玩真的。

我们团队有个不成文的规定,叫“黑色星期五下午”。每周五下午4点,我会随机挑选一个核心服务,对其进行“破坏”。

刚开始,手段极其原始:手动停止数据库服务,或者强行Kill掉某个微服务的进程。

记得第一次演练,我停掉了测试环境的MySQL从库。理论上,代码里配置了读写分离和自动切换,应该无感才对。结果呢?整个电商下单流程直接报错500。

排查发现,是一个写了三年的遗留代码块里,硬编码了从库的IP地址,根本没走配置中心的逻辑。

如果不做这次演练,这个雷大概率会在下一次大促的主从切换中引爆。这次“拔网线”的成本是0,修复成本是10分钟代码修改;而如果发生在生产环境,损失可能是六位数的GMV。

对于小团队,第一步不需要任何工具,只需要负责人有勇气在群里喊一声:“我要关服务了,大家看日志!”

写几个Shell脚本,模拟“真实”烂网络

手动关服务只能测试“死透了”的情况,但真实世界里,最可怕的不是服务挂了,而是服务“半死不活”。比如网络高延迟、丢包、磁盘写满。

这时候,Linux自带的工具就是最好的帮手。无需引入ChaosBlade或Chaos Mesh等重型框架,几个简单的Shell脚本就能模拟80%的故障场景。

我们常用的一招是模拟“网络延迟”。很多开发在本地调试时网络环境完美,一旦上线跨机房调用,稍微一点延迟就能把线程池拖死。

我常用这个脚本片段来模拟慢SQL或第三方接口超时:

# 使用 tc (Traffic Control) 让 eth0 网卡对 3306 端口的包延迟 3000ms
# 模拟数据库极度卡顿的场景

# 添加规则
tc qdisc add dev eth0 root handle 1: prio
tc qdisc add dev eth0 parent 1:3 handle 30: netem delay 3000ms
tc filter add dev eth0 protocol ip parent 1:0 prio 3 u32 match ip sport 3306 0xffff flowid 1:3

# 验证效果后,别忘了删除规则!
# tc qdisc del dev eth0 root

有一次,我们用这个脚本模拟支付网关延迟3秒。结果发现,前端页面并没有显示“处理中”,而是直接让用户可以点击第二次“支付”按钮。这直接导致了重复扣款的严重Bug。

修复方案不是去优化网络,而是迫使前端加了防抖,后端加了幂等性校验。 这就是低成本演练的价值:用几行代码的脚本,逼出业务逻辑的漏洞。

全员参与的“找茬游戏”,而不是运维的独角戏

在小团队做故障演练,最大的阻力往往不是技术,而是人心。开发人员会觉得:“你没事找事干嘛?我功能都开发不完。”

为了解决这个问题,我把演练变成了一种“游戏”。

我们设立了一个“破绽奖金池”。每次演练前,我作为“蓝军”发动攻击(执行脚本),开发人员作为“红军”负责防守(报警、排查、恢复)。

配图

  • 如果在演练中,监控系统没有在3分钟内报警,我要请全组喝奶茶;
  • 如果开发人员在10分钟内定位并恢复了故障,或者系统自动降级成功,公司给当月团建基金加500块。

这个机制运行了两年,效果出奇的好。

以前大家看到报警就烦,现在报警一响,大家眼睛都亮了,比谁手速快。更重要的是,它倒逼了监控体系的完善

最开始我们只有CPU和内存监控,根本发现不了业务层面的异常。经过几次演练,大家主动补齐了:

  • API接口响应时间的P99监控
  • 线程池活跃线程数监控
  • 关键业务(如下单量)的环比跌幅报警

现在,即使我不在公司,随便一个后端入职满三个月的新人,都知道在收到“支付成功率下跌”报警时,应该先看哪几个看板,先检查哪个依赖服务。这种“肌肉记忆”,是靠一次次演练喂出来的。

写在最后

故障演练并不需要高大上的名字,也不需要庞大的基础设施。对于中小团队来说,它就是一场定期的“消防演习”。

你不需要等到像Google那样拥有SRE团队才开始。哪怕你现在只有两台服务器,只要你不想半夜被电话叫醒,就可以开始尝试。

如果非要给一个落地的行动清单,我建议你明天上班就做这三件事:

  1. 盘点单点依赖:找出一个挂掉会导致全站不可用的服务(通常是Redis或某个中间件)。
  2. 写一个破坏脚本:利用iptablestc,写一个能模拟该服务断连或高延迟的脚本。
  3. 定个闹钟:下周二下午闲时,在测试环境运行它,叫上核心开发一起看日志,看看系统到底是优雅降级,还是直接报错。

最后做一个小调查: 你是更倾向于定期(如每周五)的明牌演练,还是更喜欢不打招呼的突袭式演练? A. 定期演练,稳扎稳打 B. 突袭演练,刺激真实 在评论区告诉我你的选择,或者分享一个你印象最深的“炸库”经历。