太长不读
真英雄最终都不会在半夜里爬起来抢修生产事故,因为他们会聪明地使用分布式系统稳定性设计,以及混沌工程,避免将自己陷入如此凄惨的境地。
作为一名开发人员,如何能让自己能逐渐减少在半夜爬起来抢修生产事故的次数?可以尝试使用本文要介绍的“分布式系统稳定性设计关键清单”。
如何让队友不会半夜把你喊起来帮着抢修生产事故?影响领导,尝试使用混沌工程,来让团队成员都在上班时间,主动发现并修复分布式系统的漏洞,逐渐减少夜里喊你的次数。
半夜爬起来抢修生产事故的是真英雄吗?
不是。真英雄最终都不会在半夜里爬起来抢修生产事故。为什么?且听下面的故事。
我以前很崇拜那些能修复各种软件缺陷的“救火”高手。
很多年前,我曾经在一个维护遗留系统的团队做过开发。
团队的每个开发,都轮流带一个7x24小时开机的手机,处理用户问题。
团队里有一位英雄。他戴眼镜,经常身穿一件白大褂。
我们要是有搞不定的各种疑难杂症,就会找他。
他能搞定80%的问题。所以过去了十多年,我依然很佩服他,觉得他是英雄。
但当年团队还是火情不断,我们这些普通水平的开发人员,还是救不了火。
前段时间在“得到”听华杉的孙子兵法。
孙子说:善战者,无智名,无勇功。
因为善于作战的人,会始终设法让自己在局部能比敌人更强大,又不错过敌人犯错的机会,所以每次胜利都轻轻松松。
“战胜而天下曰善,非善之善者也”。
如果你打了一场漂亮战,全天下的人都说太漂亮了,那不一定是什么好事。为什么?因为这是侥幸,重复不了第二回。
华杉讲起了扁鹊的故事。
扁鹊是一个名医,有一次魏文侯问他:“听说你们家兄弟三个人都是医生,那谁的医术最好?”
扁鹊就说,“我们家大哥医术最好,二哥差一点,我是最差的。”
魏文侯就不明白了:“你是天下名医啊,你大哥和二哥都没有听说过。”
扁鹊就解释:“我大哥治病是在病情发作之前,病人自己还不觉得有病,大哥就下药,铲除了病根。所以他的医术很难被人家认可。”
“我的二哥没有大哥那么大本事,在病情发作之前他发现不了。但在病情初起症状不十分明显的时候,二哥能够药到病除,所以村里人会觉得二哥还能治点小病。所以他的名气只能在本村,邻村的人都不知道他。”
“我的动静就会比较大。我治病都是在病情十分严重,病人痛苦万分的时候。我在病人的经脉上穿刺,有时候甚至还敷上毒药来以毒攻毒。最后这个病人可能得到了缓解,甚至还有治好的。所以我就名闻天下了。”
要每天治小病,而不要每年治大病。
每天治小病,花钱少,痛苦少,治得好,百岁老。
以前听到这个熟悉的故事,并没有什么感受。但最近这一次听,却颠覆了对英雄的认知。
我以前所认为的英雄,其实并不善战,而只是运气好。
而真英雄,是能把需要半夜爬起来抢修的生产事故,化解成一个个小任务,在白天上班时间给解决了。还需要半夜里爬起来吗?
有人会说,我刚刚毕业,加入一家公司,接手了一套“祖传代码”,经常需要半夜爬起来抢修生产事故。这该咋整?
如何让自己很少在半夜爬起来抢修生产事故?
可以在自己日常开发新代码,或解决软件缺陷时,经常浏览和思考下面的“分布式系统稳定性设计关键清单”,来检查相关的代码,是否踩了系统稳定性的“反模式”?如果是,那么可以用系统稳定性的“模式”这些“解药”来解决。
这样,就能把需要半夜抢修的事故,逐渐分解到日常开发中,在白天上班时逐一解决。让自己能睡个好觉。
其中,反模式和模式前面的编号,分别是《发布!》第二版第4章和第5章的小节号,方便查阅。
如果不明白后面“解药”的含义,可以查阅后文“解药的解释”一节。
分布式系统稳定性设计关键清单
反模式场景 | 反模式编号、名称及含义 | 解药 |
---|---|---|
系统的用户 | 4. 用户:用户流量的增长,是否会超过系统的容量? | 1. 超时、2. 断路器、6. 任其崩溃并替换、5. 快速失败、10. 卸下负载、9. 中间件解藕、8. 考验机 |
系统的用户 | 6. 自黑式攻击:系统是否存在漏洞,使得被人利用来危害自身? | 9. 中间件解藕 |
子系统之间 | 1. 集成点:是否存在传入数据的某个连接,令系统停止响应? | 1. 超时、2. 断路器、6. 任其崩溃并替换、5. 快速失败、10. 卸下负载、9. 中间件解藕、8. 考验机 |
子系统之间 | 2. 同层连累反应:是否由于一台服务器停机,令其他服务器必须接过其负载而不堪重负? | 3. 舱壁、6. 任其崩溃并替换、10. 卸下负载、8. 考验机 |
子系统之间 | 3. 层叠失效:是否存在某一层的失效,导致其调用层发生失效的情况? | 1. 超时、2. 断路器、9. 中间件解藕、7. 握手、8. 考验机 |
子系统之间 | 5. 线程阻塞:是否存在访问的线程都被阻塞的情况? | 1. 超时、2. 断路器、6. 任其崩溃并替换、9. 中间件解藕 |
子系统之间 | 7. 放大效应:是否存在“多对一”或“多对少”的关系的多方规模增大,使得另一方遭受放大的影响而崩溃的情况? | 1. 超时、2. 断路器、6. 任其崩溃并替换、5. 快速失败、10. 卸下负载、11. 背压机制、9. 中间件解藕、8. 考验机 |
子系统之间 | 8. 失衡的系统容量:是否存在一个层级或服务向另一个发送超过后者处理能力的大量请求的情况,从而淹没后者? | 1. 超时、2. 断路器、6. 任其崩溃并替换、5. 快速失败、10. 卸下负载、11. 背压机制、9. 中间件解藕、8. 考验机 |
子系统之间 | 9. 一窝蜂:是否存在以下情况——当启动多台服务器(如在代码升级和重新启动之后),或一个cron作业在任何一个整点时间被触发,或当配置管理系统推出一个变更时,一堆服务器同时对某一台服务器(如数据库)施加瞬时负载? | 1. 超时、2. 断路器、6. 任其崩溃并替换、5. 快速失败、10. 卸下负载、11. 背压机制、9. 中间件解藕、8. 考验机 |
子系统之间 | 10. 做出误判的机器:是否存在对于系统预期状态的“信念”,在自动化平台与管理员之间发生了冲突? | 12. 调速器、8. 考验机 |
子系统之间 | 11. 缓慢的响应:是否存在无休止地等待响应? | 1. 超时、2. 断路器、6. 任其崩溃并替换、5. 快速失败、10. 卸下负载、11. 背压机制、9. 中间件解藕 |
子系统之间 | 12. 无限长的结果集:是否存在当查询数据库、遍历结果集并处理每一行结果的程序时,没有明确限制可以处理的结果数量? | 4. 稳态、8. 考验机 |
“解药”的解释
解药,即解决相应反模式的系统稳定性的模式。
模式编号与名称 | 模式含义 |
---|---|
1. 超时 | 只要认为响应不会到来,就可以停止等待 |
2. 断路器 | 如果调用执行成功,那么一切平安无事。但如果调用执行失败,断路器会将其记录下来。一旦失败次数或频率超过阈值,断路器将跳闸并“断开电路” |
3. 舱壁 | 能将船分隔成若干独立的水密隔间的隔板,可防止水从一个部分流到另一个部分。使得船体即使被洞穿一次也不会沉没,从而控制损害范围 |
4. 稳态 | 针对每个累积资源的机制,要相应存在另一个机制以回收该资源 |
5. 快速失败 | 如果系统无法满足SLA要求,则需要快速通知调用者。不要让调用者等待错误信息,也不要让他们等到超时为止。否则只会让你的问题成为他们的问题 |
6. 任期崩溃并替换 | 创建系统级稳定性所能做的最好的事情,就是放弃组件级的稳定性,并尽快更换组件,以回到系统最初干净的刚完成启动的状态 |
7. 握手 | 发送方和接收方两个设备之间用于规范两者之间通信方式的过程,让服务器通过限制自己的工作量来保护自己 |
8. 考验机 | 能够用网络错误、协议错误或应用程序级错误等各种低层错误,来“考验”被测软件的测试服务器。因为每个系统最终都会偏离接口规范 |
9. 中间件解藕 | 通过在系统之间传递数据和事件的中间件来实现集成;通过让参与其中的系统不必了解其他系统的特定知识,而只是对其进行调用,来实现解耦 |
10. 卸下负载 | 当负载过高时,就开始拒绝新的工作请求。这与快速失败模式相关 |
11. 背压机制 | 请求的消费方将其处理请求的速度通知发送方,让自己能慢些工作,从而创造安全性 |
12. 调速器 | 减缓缺乏判断能力的自动化机制出错时的速度,从而为纠正错误争取时间 |
如果按照上面的方法,能做到自己很少在半夜爬起来抢修生产事故,但保不齐你的队友没有掌握这套方法,结果半夜把你喊起来,帮着抢修生产事故。这该咋整?
如何让队友不会半夜把你喊起来帮着抢修生产事故?
当然你可以把上面那套方法及其成效,分享给和你关系不错的队友。
但更有效的方法,是设法影响你的技术领导,请他了解《发布!》第2版最后一章所介绍的新实践——混沌工程。
早在2008年,Netflix公司在把数据中心迁往亚马逊云平台的时候,踩了一个大坑,经常会出现生产事故。为了能在白天上班时间解决生产环境的事故,而不是半夜爬起来解决,他们摸索出一套行之有效的方法——混沌工程。
可以自己阅读并请领导阅读这篇文章“【混沌工程入门】领导让我做混沌工程……该咋做?——《混沌工程》动物书2020年4月英文版解读之一”。
然后从那篇文章后面所介绍的“摆正心态、人员主动和试点业务”三方面入手,来启动混沌工程,从而让这个试点业务的每个团队成员,逐渐成为不会把自己逼到夜里就火份儿上的“真英雄”,这样他们也不会半夜喊你帮忙了。
需要注意的是,因为那篇文章重点是混沌工程,而不是本文所讨论的“分布式系统稳定性设计”,所以并没有在“该咋做混沌工程”中,体现前面说到的稳定性设计。
为了弥补这个缺憾,下面把稳定性设计补上,并用黑体字标出补充的内容。
该咋做混沌工程?
借鉴Netflix的实例,可以从“摆正心态、人员主动和试点业务”三方面入手,来启动混沌工程。
摆正心态
承认暗债为复杂系统所固有,而不是一味要求工程师“不能也不该出现失误”。否则在故障面前,大家就只会花大量时间相互甩锅,耽误了发现更多暗债和防范措施。
人员主动
前面说过,根据必要多样性法则,要建立对系统能够承受生产环境的动荡的信心,需要针对生产环境“丰富多彩”的暗债,设计同样“丰富多彩”的防范手段。而技术骨干一个人,是发现不了那么多暗债,并找到那么多的防范手段的。所以,就需要发挥各位工程师的主动性。此时,领导者要创造能调动工程师主动性和创造性的企业文化,来促进工程师更安全地发现与修复更多“花样”的暗债。在修复暗债的过程中,就可以使用上述“分布式系统稳定性设计关键清单”。
试点业务
选择一个出现生产事故频率较高的业务系统,尝试混沌工程。因为事故的反复,出现会让发现与解决暗债的动力更大
基于能反映用户体验的业务稳态行为建立假设,而不是先聚焦于在系统内寻找弱点。因为这样能更利于进行全局优化,让成效更大
为了让暗债浮现出来,设计引入足够多样化的现实世界可能发生的事件,而不是设计那些易于生成但在现实中不大可能出现的事件,以便切中要害。针对每一个所引入的事件,参考上述“分布式系统稳定性设计关键清单”,来进行稳定性设计
可以先从准生产环境入手进行混沌实验,等条件成熟后,再逐渐过渡到生产环境
自动化地持续进行混沌实验,以起到回归实验的效果,持续发现并解决暗债,避免系统随着时间的推移,在韧性方面逐渐“掉队”
设计更安全的实验方式,以最小化爆炸半径,让实验所导致的业务损失降到最低,而不是明知故障难以控制,还要贸然进行实验。如果实验的假设被证伪,那么就遇到了发现新的暗债的好机会。在寻找暗债的过程中,可以参考上述“分布式系统稳定性设计关键清单”,来启发寻找漏洞及修复