某跨境电商网站曾涌现一次搜索功能挂掉的情形。某天,该电商网站溘然接到大量的用户反馈,称该电商网站的主搜功能无法利用,通过关键字搜索并没有结果展现,导致交易量急剧下跌。同时,监控告警提示该电商网站的交易量下跌、搜索展现下跌等。
该电商网站的开拓职员第一韶光排查问题,创造在几分钟前有一次代码发布,在快速回滚后功能规复。他们通过代码审查,创造在本地发布中只有一行代码改动,即在数据的分页查询中,某开拓职员将pageSize从10改成了50。按理说这种小的改动不会影响到搜索功能,但一位有履历的开拓职员第一韶光指出了问题:由于某种缘故原由,在代码中有一个默认设置:当搜索结果大于即是50的时候,就默认不返回任何结果。
导致该故障的成分有很多,下面进行大略剖析。

◎ 这个默认设置当初是一个“临时方案”,但是一贯没被改过。这便是技能债的问题。
◎ 如果不仔细阅读代码,就无法创造这个默认设置,由于这个故障在任意文档中都没有记载,并且没有被其他开拓职员提到,更主要的是,在上线前未经由代码审查。这便是人、流程与文档之间的博弈问题。
◎ 在代码上线之前未经由测试。开拓职员认为这只是一个很小的改动,不会有什么问题,以是就直接发布了。这便是质量意识淡薄的问题,也适值印证了墨菲定律:未经由测试的功能每每存在问题。
运用竟然被外部系统拖垮了在浩瀚线上故障中,有一类故障比较分外,故障的起因可能来源于外部,也很可能是我们依赖的某个不主要的系统涌现了非常,导致运用涌现线上故障。这便是范例的“蝴蝶效应”。
例如,在某个故障中,某网站的用户反馈网站相应变慢,乃至涌现相应码为500的做事器非常缺点,线上机器大量告警,涌现频繁的CMS GC。开拓职员第一韶光对机器的堆栈进行Dump(转储),创造ThreadLocal中的一个工具占用了大量的内存。在剖析代码时,他们创造在ThreadLocal中保存了一个Map作为本地缓存,在这个Map中保存了很多缓存工具,每次在读取缓存数据时,都会先从 ThreadLocal 中获取这个工具实例。在须要向缓存中保存数据时,就直接向这个ThreadLocal中的Map保存数据,导致这个Map越来越大。
这实在并不是导致频繁CMS GC的关键,由于在这个故障发生之前,线上环境平稳运行了很长一段韶光。那么,到底是什么导致了频繁的CMS GC呢?
经由开拓团队的辛劳排查,结果很是让人出乎猜想:竟然是在运用中依赖的一个外部系统溘然变慢,导致本运用的功能涌现非常。由于外部系统相应变慢,要求外部系统的韶光就会变长,以是在同一时候存活的线程数变多了。由于每个线程都复制了一份ThreadLocal的数据,以是,ThreadLocal占用的内存也变多了,这就发生了CMS GC;又由于外部系统一贯没有好转,线程数越来越多,以是发生了频繁的CMSGC。
这便是范例的“蝴蝶效应”导致的故障:一个不主要的系统性能变差,触发了另一个别系发生Bug,从而导致严重的线上故障。
HashMap与并发广大Java工程师对HashMap再熟习不过了,HashMap是非线程安全的,也是Java口试中的必考题目。但是,HashMap在并发场景下涌现的问题在很多公司和技能团队中都发生过,乃至在淘宝早期就发生过由于在并发场景下利用HashMap导致CPU被打满的线上故障。
阿里巴巴的研究员毕玄在自己的博客中曾经记录过这样一个案例:某天中午,开拓职员收到大量的线上告警,提示某些机器的负载超过了500。开拓职员便赶紧登录线上机器,利用top命令查看了CPU的情形,创造CPU花费靠近100%,于是又通过shift h命令查看线程的情形,创造并没有CPU花费较高的线程,花费量基本在0.7%旁边,但线程总数看起来很多。于是,开拓职员通过ps-eLf|grep java-c命令统计了线程总数,创造一共有700多个线程,以是又连续实行了几个jstack命令查看线程堆栈,创造个中有600个线程处于RUNNABLE状态,并且都在实行HashMap的get方法。根据履历,基本可以断定问题是由于在并发场景下缺点利用HashMap导致的。
在该案例中,开拓职员根据堆栈信息找到了相应的出问题的类名,然后找到了相应的jar,用jd-gui反编译看了下相应的代码,创造在代码中利用此HashMap的办法如下:
堆栈中的信息显示有 600 个线程在实行 caches.get(key)。之前之以是在这个地方利用HashMap,并且没有加锁,因此为load方法只会在Spring初始化当前这个bean的时候实行一次,但不幸的是随着业务的发展,这个load方法在数据变更时会被触发,可能涌现向Cache里放东西的时候,而其他线程在取东西,这就直接导致了并发问题。关于HashMap的去世循环问题,可以搜索干系资料理解细节。
当然,涌现这个CPU花费高的征象不是HashMap的问题,还是利用的问题,因此对这个问题的修复也很随意马虎,便是用ConcurrentHashMap来更换HashMap。
“high cpu usage in hashmap.get” 是 在 Google 上 搜 索“hashmap”时涌现的热词,可见这个缺点很常见,比如 Velocity、Hessian 都涌现过类似的缺点。Hessian 老版本中的类似Bug可以拜会http://bugs.caucho.com/view.php?id=1588;Velocity老版本中的类似Bug可以拜会https://issues.apache.org/jira/browse/VELOCITY-718。
在以上案例中之以是涌现故障,紧张还是由于技能债导致的。由于在方案设计初期没有考虑到业务发展可能带来的变革,在无意中引入了“临时方案”,就欠下了技能债,进而导致故障的发生。
故障复盘流程及模板在软件行业,一次线上故障的处理流程紧张分为三个大方面:故障创造、故障处理及故障复盘,如图6.18所示。
图6.18
故障创造和故障处理是很多公司都比较重视的两个环节,故障复盘却被常常忽略,本节就来聊聊和故障复盘有关的事情。
什么是故障复盘“复盘”原是围棋术语,本意是对弈者不才完一盘棋之后,重新在棋盘上把对弈过程摆一遍,看看哪些地方下得好,哪些地方下得不好,哪些地方可以有不同乃至更好的下法等。这种把对弈过程还原并且进行研讨、剖析的过程,便是复盘。“故障复盘”也是如上所述的过程,只不过不是针对棋局,而是针对一次“血淋淋”的线上故障。故障复盘会对故障处理的全体流程做一个“回放”,有利于我们深入剖析和总结在故障处理的过程中哪里做得好,哪里做得不好,有哪些地方可以有更好的做法等。
为什么要做故障复盘很多公司和团队都不重视故障复盘,究其缘故原由紧张有两点:对故障复盘有误解;不知道故障复盘的浸染及主要性。
说到故障,就一定会有定责,不管在什么样的公司,这都是比较敏感的话题。发生一次线上故障,小则影响开拓职员的绩效考察,大则可能导致高层引咎辞职,以是很多人在办理故障后都会下意识地抗拒重新提起发生故障的细节,尤其是和本次故障有直接关系的人或者团队。这个中的最紧张缘故原由是很多人对故障复盘存在误解,认为故障复盘的目的便是“分锅”和“甩锅”。不可否认,自我反思与相互批评是故障复盘中很主要的一个环节,但是,这并不是故障复盘的终极目的。故障复盘的终极目的实在是通过对已经产生的故障的反思,进行总结及优化。
笔者认为,故障复盘紧张有如下目的。
◎ 对已发生的故障进行总结,避免再次涌现同样和类似的问题。
◎ 找出团队的强弱项,优化职员分工和办事流程。
◎ 考试测验找到更好的问题办理办法。
◎ 进行履历总结,分享沉淀,引起大家的广泛重视。
如何做故障复盘前面先容过故障复盘的目的和主要性,接下来看看如何进行一次有效的线上故障复盘,紧张通过故障复盘的哀求及流程进行展开。
1.故障复盘的哀求
故障复盘是故障处理中至关主要的环节,我们对其自然不能搪塞了事。一次规范的故障复盘须要知足如下6个哀求。
◎ 故障复盘要及时,复盘韶光间隔故障办理的韶光最好不要超过一周。
◎ 在故障复盘之前,干系职员应对本次故障的背景有基本理解。
◎ 在复盘过程中不批评、不表扬,就事论事,只陈述事实。
◎ 在故障复盘时要有完全的过程回溯,例如为什么会发生、第一韶光如何办理等。
◎ 在故障复盘时对故障进行深层次的阐发,例如是否是流程存在问题、是否有更好的办理方案等。
◎ 在复盘后要有内容产出,例如故障复盘文档、复盘关照邮件、切实可行的行动(后续行动点)及行动点验收方案等。
阿里巴巴高等运维专家胡杨曾经总结过一套“RASA”理论,RASA即 Review ( 回 顾 ) 、 Analyze ( 分 析 ) 、 Summary ( 总 结 ) 和Action(行动),如图 6.19 所示。该理论和以上先容的故障复盘的哀求不谋而合,都关注过程的回溯、深层次的阐发、履历总结及后续行动点的跟进。
图6.19
2 故障复盘的流程
前面先容了一次规范的故障复盘须要知足的几点哀求,那么在一次完全的故障复盘过程中都须要做哪些事情呢?
故障复盘一样平常包含如下几个流程:故障记录、故障剖析、复盘会议、行动点制订和行动点验收等,如图6.20所示。
图6.20
1)故障记录
故障记录一样平常由任务开拓或者测试职员卖力,有些公司可能由专门处理故障的做事支持职员卖力。不管是谁来卖力记录故障,都须要担保信息尽可能客不雅观、准确,这样才能在后续的复盘过程中供应准确的信息。
故障记录紧张包含如下内容:故障发生韶光、故障描述、影响范围、紧张模块、干系任务人、故障处理职员、故障处理时效、故障确当前状态、故障办理韶光、故障办理方案、故障缘故原由、故障定级等。
在故障记录过程中,有一个比较关键的步骤便是进行故障定级。
故障定级根据不同的业务有着不同的指标,常日可以参考的指标有:
影响用户数、故障规复韶光、用户投诉数、资金丢失数、模块主要性等。
不同的公司对故障的级别有不同的定义,一样平常会有 P1、P2、P3、P4等几类故障,这里的P是Priority Level的缩写。如表6.1所示是钉钉公开的开拓文档中关于《运用故障定级标准》中故障等级的描述(拜会https://opendoc.dingtalk.com/microapp/operations/hn94hh)。
本文给大家讲解的内容是程序员架构修炼: 踩过的坑和履历总结、故障复盘流程及模板;
表6.1
可以看出,对付一个核心模块的功能,可根据用户操作失落败率、每分钟失落败量及影响韶光等条件划分出4个等级。
有了故障定级,就可以针对不同级别的故障确定须要哪些人关注这次故障、故障规定处理时效,以及后续复盘会议参与职员及在故障定责时确定奖罚等级等。
2)故障剖析
故障剖析紧张由故障干系任务人、故障处理职员等卖力,旨在深入剖析故障发生的根本缘故原由、在故障办理过程中是否有可优化的步骤等。
在这个过程中,剖析职员须要不断提出5W1H等干系问题,例如:
◎ 是什么缘故原由导致了本次故障(Why)?
◎ 故障发生在什么业务、模块和功能点中(What)?
◎ 故障是在什么韶光发生的、开拓职员在什么韶光开始接入的,
以及在什么时候规复的(When)?
◎ 故 障 发 生 在 什 么 环 境 下 、 对 哪 些 地 区 的 用 户 有 影 响(Where)?
◎ 本次故障是谁创造的、谁办理的,以及谁该负紧张任务(Who)?◎ 故 障 是 怎 么 定 位 的 、 怎 么 解 决 的 , 有 没 有 更 好 的 办 法(How)?
通过不断追问,抽丝剥茧,洞察故障实质。
3)复盘会议
故障复盘会议常日由故障台事情职员或者故障任务团队牵头,约请干系的开拓卖力人、质量卖力人、产品卖力人乃至运营卖力人一起进行。在复盘会议上须要对本次故障及故障处理过程进行总结、谈论及反思。在某些情形下还会进行故障定性、故障定责等。
根据故障发生的模块、发生的缘故原由等可以对故障进行定性和定责,即确定本次故障的性子、须要对本次故障卖力的干系职员或者团队等。在定性和定责时须要明确出哪些个人(团队)对本次故障承担紧张任务,哪些个人(团队)对本次故障承担次要任务,定责过程要公正、公道、公开,做到权责同等、边界清晰。
4)行动点制订
在故障复盘会议中,除了要对故障进行剖析和总结,一件必不可少的事情便是实行后续行动点。根据详细的故障,行动点可能有多种,比如代码优化、流程优化乃至组织架构优化等。但无论详细的行动点是什么,制订的行动点都须要知足如下条件。
◎ 必须是明确的项,要有明确的行动点,不能是大而空的方案。
◎ 必须可落地,能够切实改进既有问题。
◎ 必须可验收,有明确的验收标准。
◎ 必须承诺验收韶光,并且要在原则上按照承诺的韶光完成。
5)行动点验收在实行行动点之后,须要进行定期验收,还要对行动点周期性地跟进和确认。在验收时,要严格对照验收标准,确保行动点真实、可靠地落地。
故障复盘模板前面先容了什么是故障复盘、为什么做故障复盘,以及如何做故障复盘等内容,相信读者已经对故障复盘有了一些基本理解。接下来会给出一份故障复盘模板,如表6.2所示。故障复盘模板,实在便是在故障复盘会议上须要大家剖析、谈论及总结的内容模板,也可以称之为故障复盘记录模板。
表6.2
须要把稳的是,故障复盘记录和前面先容过的故障记录并不是一回事,故障记录指的是在故障发生之后对该故障跟进内容的干系记录,故障复盘记录则指的是复盘会议中的会议记录。
下篇文章给大家讲解的是程序员架构修炼:架构的保障,监控与告警、应急处置;以为文章不错的朋友可以转发此文关注小编;感谢大家的支持