Files
CategoryResourceRepost/极客时间专栏/左耳听风/技术基础/17 | 故障处理最佳实践:应对故障.md
louzefeng d3828a7aee mod
2024-07-11 05:50:32 +00:00

76 lines
8.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<audio id="audio" title="17 | 故障处理最佳实践:应对故障" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/6f/92/6f85a9a3ffbe3a36662294aa03482292.mp3"></audio>
或多或少我们都会经历线上的故障。在我的职业生涯中,就经历过很多的线上故障。老实说,线上故障是我们技术人员成长中必须要经历的事。从故障中我们可以吸取到很多教训,也能让我们学到很多书本上学不到的知识。坑踩多了,我们会变得越来越有经验,也就成为老司机了。
不过,我看到很多公司处理线上故障的方式并不科学,而且存在很多问题,所以,今天这篇文章就来分享一些我的经验。这些经验主要来自亚马逊和阿里这两家互联网公司,以及我个人的经验总结。希望这套方法能够对你有帮助。
# 故障发生时
在故障发生时,最重要的是快速恢复故障。而快速恢复故障的前提是快速定位故障源。因为在很多分布式系统中,一旦发生故障就会出现“多米诺骨牌效应”。也就是说,系统会随着一个故障开始一点一点地波及到其它系统,而且这个过程可能会很快。一旦很多系统都在报警,要想快速定位到故障源就不是一件简单的事了。
在亚马逊内部每个开发团队至少都会有一位oncall的工程师。在oncall的时候工程师要专心处理线上故障轮换周期为每人一周。一旦发生比较大的故障比如S1全部不可用或S2某功能不可用而且找不到替代方案那么这个故障就会被提交到一个工单系统里。几乎所有相关团队oncall的工程师都会被叫到线上处理问题。
工作流是这样的工程师先线上签到然后自查自己的服务如果自己的服务没有问题那么就可以在旁边待命standby以备在需要时进行配合。如果问题没有被及时解决就会自动升级到高层直到SVP级别。
大家都知道在亚马逊不是按技能分工而是按职责分工也就是一个团队不是按前端、后端、运维等来分工而是按所负责的Service来分工。
所以,亚马逊的开发人员都是前端、后端、测试、运维全部都要干的。而亚马逊内部有很多的服务,一旦出现问题,为了避免一个工单在各个团队流转,需要所有团队上线处理,这样是最快的。
如果我们的系统架构是分布式服务化的,那么一个用户的请求可能会经过很多的服务,开发和运维起来是非常麻烦的。此时,跨团队跨部门的开发和运维就变得非常重要了。
就我的经历而言,在故障发生时,亚马逊的处理过程是比较有效和快速的,尤其是能够快速地定位故障源。对于被影响的其他团队也可以做一定的处理,比如做降级处理,这样可以控制故障的范围不被扩散。
故障源团队通常会有以下几种手段来恢复系统。
<li>
**重启和限流**。重启和限流主要解决的是可用性的问题,不是功能性的问题。重启还好说,但是限流这个事就需要相关的流控中间件了。
</li>
<li>
**回滚操作**。回滚操作一般来说是解决新代码的bug把代码回滚到之前的版本是快速的方式。
</li>
<li>
**降级操作**。并不是所有的代码变更都是能够回滚的,如果无法回滚,就需要降级功能了。也就是说,需要挂一个停止服务的故障公告,主要是不要把事态扩大。
</li>
<li>
**紧急更新**。紧急更新是常用的手段这个需要强大的自动化系统尤其是自动化测试和自动化发布系统。假如你要紧急更新1000多台服务器没有一个强大的自动化发布系统是很难做到的。
</li>
也就是说,出现故障时,**最重要的不是debug故障而是尽可能地减少故障的影响范围并尽可能快地修复问题**。
国内的很多公司,都是由专职的运维团队来处理线上问题的。然而,运维团队通常只能处理一些基础设施方面的问题,或是非功能性的问题。对于一些功能性的问题,运维团队是完全没有能力处理的,只能通过相应的联系人,把相关的开发人员叫到线上来看。
而可能这个开发人员看到的是别的系统有问题,又会叫上其它团队的人来。所以,一级一级地传递下去,会浪费很多时间。
# 故障前的准备工作
为了能够在面临故障时做得有条不紊,我们需要做一些前期的准备工作。这些准备工作做得越细,故障处理起来也就越有条理。我们知道,故障来临时,一切都会变得混乱。此时,对于需要处理故障的我们来说,事可以乱,但人不能乱。如果人跟着事一起乱,那就是真正的混乱了。
所以,我们需要做一些故障前的准备工作。在这里,我给出一些我的经验。
<li>
**以用户功能为索引的服务和资源的全视图**。首先我们需要一个系统来记录前端用户操作界面和后端服务以及服务使用到的硬件资源之间的关联关系。这个系统有点像CMDB配置管理数据库但是比CMDB要大得多是以用户端的功能来做索引的。然后把后端的服务、服务的调用关系以及服务使用到的资源都关联起来做成一个视图。
这个视图最好是由相应的自动化监控系统生成。有了这个资源图后,我们就可以很容易地找到处理故障的路径了。**这就好像一张地图,如果没有地图,我们只能像个无头苍蝇一样乱试了**。
</li>
<li>
**为地图中的各个服务制定关键指标,以及一套运维流程和工具,包括应急方案**。以用户功能为索引,为每个用户功能的服务都制定一个服务故障的检测、处理和恢复手册,以及相关的检测、查错或是恢复的运维工具。对于基础层和一些通用的中间件,也需要有相应的最佳实践的方法。
比如Redis怎样检查其是否存在问题怎样查看其健康和运行状态哪些是关键指标面对常见的故障应该怎么应对服务不可用的服务方案是什么服务需要回滚了应该怎么操作等等。**这就好像一个导航仪,能够告诉你怎么做。而没有导航仪,就没有章法,会导致混乱**。
</li>
<li>
**设定故障的等级**。还要设定不同故障等级的处理方式。比如亚马逊一般将故障分为4级1级是全站不可用2级是某功能不可用且无替代方案3级是某功能不可用但有替代方案4级是非功能性故障或是用户不关心的故障。阿里内的分类更多样一些有时会根据影响多少用户来定故障等级。
制定故障等级主要是为了确定该故障要牵扯进多大规模的人员来处理。故障级别越高牵扯进来的人就越多参与进来的管理层级别也就越高。就像亚马逊的全员上线oncall一样。**这就好像是我们社会中常用的“红色警报”、“橙色警报”、“黄色警报”之类的,会触发不同的处理流程**。
</li>
<li>
**故障演练**。故障是需要演练的。因为故障并不会时常发生但我们又需要不断提升处理故障的能力所以需要经常演练。一些大公司如Netflix会有一个叫Chaos Monkey的东西随机地在生产线上乱来。Facebook也会有一些故障演习比如随机关掉线上的一些服务器。总之要提升故障处理水平最好的方式就是实践。见得多了处理得多了才能驾轻就熟。**故障演练是一个非常好的实践**。
</li>
<li>
**灰度发布系统**。要减少线上故障的影响范围通过灰度发布系统来发布是一个很不错的方式。毕竟我们在测试环境中很难模拟出线上环境的所有情况所以在生产线上进行灰度发布或是A/B测试是一件很好的事。
</li>
在亚马逊发布系统中有一个叫Weblab的系统就是用来做灰度发布的。另外亚马逊全球会有多个站点。一般来说会先发中国区。如果中国区没什么问题了就发日本区然后发欧洲区最后是美国区。而如果没有很多站点的话那么你就需要一个流量分配系统来做这个事了。
好了。今天就分享这么多。我觉得,只要能做好上面的几点,你处理起故障来就一定会比较游刃有余了。
在这篇文章的末尾,我想发个邀请给你。请你来聊聊,你所经历过的线上故障,以及有哪些比较好的故障处理方法。