本文转载自微信公众号《跨界建筑师》,作者Zachary。转载本文请联系跨界架构师公众号。作为一名程序员,相信有一件事情是大家最不愿意看到的。即在线运行的系统存在技术故障。(尤其是周末在外面开心的时候:D)处理这样的事情特别能体现一个人的综合能力。因为会涉及抗压能力、对外沟通能力、排查问题所需的技术能力等诸多方面。如果您还没有机会成为一名核心开发人员,那很少会有如此压力大的经历。因为在这种情况下处理事情其实是很慌张的。毕竟,所有使用系统的人和他们的上司,你的上级,你的上司等等,都在盯着这件事情。还记得有一年双11,我作为“首席问题解决官”,正在紧急处理服务器承受不住压力的问题。老大默默走到我面前问:“有什么问题?什么时候好?”。在你的脑海中构想这幅画,想象一下。只要你以后继续做程序员,我想你都有机会遇到这样的场景。因为一个著名的定律——墨菲定律。墨菲定律:任何可能出错的事情都会出错。如果维基百科没有明确的处理方式,一旦出现线上问题,就会像热锅上的蚂蚁,仓皇乱窜,像无头鸡一样乱撞(试试)。所以,这次我想分享一下我作为“首席问题解决官”多年的一些心得。这是承载了我汗水和脑细胞的经历。在日常的项目开发迭代过程中,我们遇到了一个bug。大家的处理流程都差不多:定位bug->解决bug。可能有一小部分人在解决bug后会思考和review,看看有没有类似的bug,一起处理。这种“定位->解决->复习”的过程同样适用于线上问题。但它必须不止于此。俗话说,解决问题最难的不是解决问题的过程,而是定位的过程。所以,对于线上的问题,我们经不起等待定位问题的时间,所以必须把“恢复”系统的正常使用放在首位。因此,流程变为:“Recover->Locate->Solve->Replay”。让我在这里再补充一件事。有人认为,以恢复系统为首要目标,应该包括牺牲保存场景的动作,因为这个动作也可能需要几分钟的时间。我不同意这种观点。究其原因,解决问题的时间长短确实是一个很重要的指标,但是既然问题已经发生了,如果后续因为没有留住现场而没有找到根本原因,而下次再出现问题,场面会更难看。所以我对这件事的观点是,最重要的是要保住现场。因此,这个过程就变成了:“保留站点->恢复->定位->解决->重播”。当然,保留现场并不意味着一定要面面俱到,需要很多时间。用最快的方式把你一时能想到的相关线索全部保留下来。如果事后因缺乏线索而无法找到根源,只能说是经验不足。考虑将来需要保留哪些现场数据。好了,既然确定了这5个步骤,那么每个步骤可以做什么呢?让我一一说。/01保留站点/保留站点最重要的是保存异常程序的转储文件。有了它,就可以摆脱盲人分析大象的局面,快速定位问题的根源。我用三个“最”来强调它的重要性。如果你还没有掌握,那我后面说的这些先放一边,先掌握吧。另外,如果系统的监控系统不完善,出现问题时需要通过截图快速保存操作系统和第三方组件的监控数据。保存监控数据时,要特别注意与网络相关的数据。如果发现网络相关数据异常,则通过命令保存当前网络连接状态。因为相对来说,无论是程序还是其他原因,网络出现问题的概率远大于硬件。系统越大,越是如此。/02恢复/恢复系统访问的方法有很多种。首先,不得不提一个适用于80%情况的神技——重启。是的,根据多年的经验,这一招在大多数情况下确实有效。也正是因为屡试不爽,很多人第一时间习惯性的重启游戏,导致场景忘记保存而损坏。重启有两种,强制重启和自然重启。当然优先考虑自然重启,可以避免一些意外的脏数据。但是如果系统出现资源消耗异常,不要等到自然重启,只能强制重启(杀掉进程)。第二种常用方法是“回滚”。当然,它的前提是你判断问题出在最新版本上。否则,盲目的回滚不仅没有用,还会把事情弄得越来越乱,尤其是在分布式系统中。因为在分布式系统中,一旦上下游耦合连接失败,就会报错,出现大量的异常数据,够你折腾半天的。第三种方法是“降级”。暂停有问题的模块并停止服务。当然这个动作需要和业务方沟通好,单独降级一个模块是否会导致业务不完整等问题。第四种方法是“限流”或“扩容”。如果发现系统无法处理突然增加的流量,可以的话可以快速扩容几台机器和程序。如果不能扩容,可以选择限流,对一定比例的请求直接拒绝服务。毕竟相比全部不可用服务和部分不可用服务,后者肯定更划算。还有一些不太流行的方法,比如“切换到备机”、“故障隔离”等,这里就不展开了。他们对环境和条件的要求更高。有时系统可能无法恢复到完全正常的状态,比如读数据没问题,但是写数据时有些操作还是有问题。遇到这种情况,先不要着急定位问题,尽量恢复到最大可用状态再进行下一步。毕竟,用户是第一位的。/03Location/关于位置的问题,如果有dump文件就最方便了。通过转储文件分析工具分析转储文件,可以快速定位到有问题的代码行,尤其是程序阻塞、内存溢出、cpu100%等明显问题。是程序本身的问题。不同的语言有不同的dump分析工具,大家可以自行上网搜索教程。最终目的是定位到异常点的堆栈信息,相当于直接定位到问题代码出现的位置。如果分析dump文件就是跳过剥茧这一步,直奔主题。通过监控数据和日志层层分析,是一件很慢的工作。但是如果dump文件丢失或者问题从来没有从dump文件中分析出来,就只能选择后者了。我们在看日志和监控数据的时候,一定要有联合看的觉悟,不能只看一个维度。因为有时候你在单一维度看到的数据看起来很正常,但是关联起来就不一定了。比如tcp连接数减少了一半,内存却增加了100%。为什么?可能有失败的线索。/04解决/定位问题,解决方法很简单。代码改成代码,配置改成配置文件。这里就不多说了,毕竟情况太多了,每个人遇到的可能都不一样。/05复习/复习的好处大家都知道,但真正去做复习的人却不多。如果你不知道从哪里开始做复习,不妨从以下问题入手。这个失败的原因是什么?到时候有没有更快的方法恢复业务呢?如何避免再次发生类似故障?现行制度中是否存在类似的潜在风险?如果你能回答这些问题,我觉得这个审核就到位了,剩下的就是执行了。当然,无论你如何处理失败,最好的事情就是不要失败。所以我们需要在前期做更多的准备。/01理解你的程序/我们中的许多人仅通过编码来理解我们负责的程序。除非程序是单体应用程序,否则这种方法是不够的。我建议你按照下面的列表来了解你的程序:程序包含哪些模块,对应的用户是谁?哪些是核心模块,哪些可以“舍弃帅”?多个模块/系统之间如何流动?(试着画个流程图加深记忆)你依赖哪些中间件,谁负责维护?您还依赖哪些其他程序,无论强弱,谁负责维护它们?依赖存储和消息队列背后的依赖是什么?仓储运维的负责人是谁?线上程序部署在什么环境?你有条件独立部署和调优吗?/02做好监控/大多数故障不是突然发生的,而是有一个逐渐积累的过程,直到爆发。因此,监控的价值不仅仅是看数据那么简单,对于异常识别尤其有帮助。通用监控分为两个维度,系统维度和业务维度。监测指标分为“环境指标”、“程序指标”、“业务指标”三层。具体做法我在之前的文章?中已经详细说明了,这里就不赘述了。如果是分布式系统,还可以搭建一个请求链接跟踪系统。有很多成熟的现成方案,如CAT、SkyWalking、Zipkin、Pinpoint等。还有一点,我们在做监控预警的时候,除了要设置阈值,还要注意波动性。例如某资源日利用率为20%,除了设置80%以上的阈值进行预警外,还需要在波动幅度超过100%时进行预警(利用率为40%),让大家提前关注。否则,一旦它以更快的速度增长到80%,你在故障爆发前消灭它的机会就很渺茫了。此外,针对常见故障预置几套故障应对预案,以及定期进行故障演练(一般只有具备一定规模的公司或处于扩张阶段的公司才会考虑),可以让团队在面对线上故障时更加事半功倍。轻松。如果你不幸是在线故障的解决者,如果你的上级不在,你需要定期向上级汇报问题处理情况,以便TA了解问题的严重程度、修复的进度并做出决定。反正就算不报,迟早会被提醒的。与其被动催促,不如主动举报。好的,总结一下。在这篇文章中,Z哥给大家分享一些处理上线故障的经验。从思路上分为“保留站点->还原->定位->解决->审核”五个步骤。除了第四步“求解”外,我都进行了扩展。预留现场。主要是保存转储文件和截图系统监控数据(外建监控系统中没有的部分)。恢复。主要是重启、回滚、降级、限流和扩容。还有一些小众的方法,比如“切换到备机”、“故障隔离”。分析转储文件,分析监控数据和程序运行日志。解决。重播。弄清楚以下四个问题就足够了:这个故障的原因是什么?到时候有没有更快的方法恢复业务呢?如何避免再次发生类似故障?现行制度是否存在类似的潜在风险?所以你要未雨绸缪,尽量减少线上故障的爆发。了解你的程序,做好监控
