一个小小的故障就可能造成巨大的负面影响,因此稳定性工作复杂却又至关重要。本文将通过故障预防、修复、复盘来讲解该如何建设一个稳定性体系。

来到阿里后,我的工作内容一直都是商品中心的稳定性,这份工作对于我个人在技术和经验上的成长提升是无比巨大的。在我看来,稳定性是一个极为复杂的工作,对人的能力考验极大,本文希望和大家一起了解:

  • 稳定性是做什么的?

  • 稳定性到底怎么做?

  • 做好稳定性,需要什么样的能力?

  • 怎么从稳定性零散的事情中创造价值?

一、什么是稳定性

1、稳定性的定义

在我看来,稳定性工作是指日常保障系统安全生产的同时,利用技术手段以及规范开发流程,使系统在不断的业务迭代中熵增达到最小化的一种工作。作为一家互联网公司,稳定性工作本质上就是保障安全生产。一个故障,就可能会造成很大的负面影响,举例几个之前有过耳闻的故障:

  • 某故障使下单阻塞,导致某线下业务受到很大影响;

  • 很多年前春节时订正数据,由于脚本问题,导致部分订单被确认收货;

  • 由于arguments版本不一致,同时进行了无灰度的操作,导致某业务大范围宕机;

由此可见,集团内部的故障,轻则影响用户体验、商家体验,重则对人民财产造成重大损失;因此,保障安全生产是企业发展的头等大事。

2、稳定性岗位的工作内容

稳定性的事情看上去可能比较散,但结合我自己的思考,我将稳定性的价值体系划分为几个方面:

1)日常稳定性

① 业务保障

大促保障、业务日常的答疑等等,通过这些事情,稳定性同学会与业务同学配合,从底层性能、技术层面,更好地推动业务向前发展。日常的答疑工作是稳定性同学投入时间最多的内容之一,很多问题都会第一时间流入到稳定性同学手中:

  • 技术问题:应用架构不了解,或由于系统稳定性问题导致上游出现限流、超时等;

  • 大促问题:很多关于大促的问题,大促跨域合作的横向事宜等;

  • 业务问题:日常碰到的影响业务体验的问题,比如某些业务出现了阻塞或者数据错误等。

对于体量较大、较为核心的团队,一天涌入的问题是很多的,我们的思考和处理方案如下:

  • 技术支持:所有问题的入口,首先通过答疑群接触到的就是技术支持同学,这部分能cover大部分的问题;

  • 每周答疑:技术支持并不深入了解底层业务和代码,对于他们无法处理的问题,会流转到每周答疑同学身上,由商品域的同学每周轮换,负责答疑和发布。

2)大促 & 活动保障

稳定性另一个核心就是负责大促和重保活动。每一次大促,上到业务,下到中台、基础设施,都需要抽出人力进行保障,每个域的稳定性同学则是其中的中坚力量。下面我着重从流程和内容上讲一下大促保障手段,可能不同同学面临的场景不同,但整个理论应该是相通的:

① 保障流程

  • 大促准备

活动开始前开始进行一系列准备工作,如入口流量、各应用容量的评估,预案、规则的梳理,建站压测等。

  • 全链路加固

这个阶段会根据正式期的流量模型进行频繁的压测来找出系统问题,建立相关的监控防线,压测会一直持续到正式期开始。

  • 作战保障

从压测期间发现的具体问题出发,逐个解决,并制定相关的作战手册等,完善大促保障机制。

  • 大促预热

这个阶段一般在大促正式期前几天开始,一般会执行一些清理和重启的任务,混部扩容以及一些提前执行的预案、预热任务等也会启动。

  • 大促保障

正式进入保障期,核心作战时间保障活动,盯盘,发现问题及时播报;峰值结束后,需要关注相关预案及资源是否下线。

② 工作内容

大促稳定性保障的工作比较复杂,在这里先放一张图,让没有参与过大促的同学来点体感:

虽然看起来简单,但真实的保障过程远比这些事情更多,面临的压力也比想象的大很多,即使在大促日渐常态化的今天,参与大促保障、经历阿里千万级复杂流量模型洗礼仍然是提高个人能力的最佳方式。

3)优化专项 & 链路治理

保障业务不断发展时,由于系统不断的迭代,必然会导致熵增,原来可能较为稳定的链路,会因为迭代而不断腐化。同时,如618、双11等大型活动,也不断挑战系统的极限。一句话来总结:业务发展(系统变更)不断的挑战着我们系统的稳定性,我们需要持续不断的进行性能优化,保障系统的高可用,来适应越来越庞大的业务。不同的优化专项,在不同的场景下做法可能也不同,风险也会比日常的需求高很多。

① 产生变更

随着业务不断的迭代,不可避免地会发生变更,如更新代码、发布配置或做运维层面的变更等,而这些变更则可能引入一些未知的问题,这些问题可能会瞬间暴露出来,或积压一段时间后喷涌式的爆发,一般来说,后者产生的影响可能会更大一些。

② 发现问题

故障定级经常会讲提前发现,如果能够提前发现故障,不仅能降低或者避免因故障带来的损失,也能将故障等级缩小。那么,如何主动发现由变更产生的问题?这一部分则要依赖稳定性建设时比较重要的一环 — 监控告警:

  • 我们在上线业务代码前,根据自己判断出的可能产生问题的点,输出的业务日志告警。

  • 容器与中间件性能相关的全景监控大盘。

  • 在线与离线等数据对账相关的大盘。

当然,监控不可能百分之百覆盖到所有的问题,也有很多问题会从其他侧反馈过来,此时就要盘点出自己的监控体系中到底还有哪些疏漏,并逐渐完善。

③ 解决问题

大致为高可用问题和数据一致性问题两类,针对不同场景有不同的解决方法,高可用问题大家可能比较熟悉了,优化起来目标也比较明确,技术难度有高有低,不详细展开讨论。

4)成本缩减

大部分的性能优化,提升系统的性能仅仅是一方面,另一个作用则是通过性能优化提高的性能压缩技术成本。同时,效能提升也是与稳定性同学有关的一件事情,通过制定更好的开发规范以及流程,来帮助同学们提高开发体验和工作效率,也可以将更多的时间投入在业务发展上,来进一步促进业务发展,从而形成一个良性循环。在我个人看来,我将成本划分为两类:

① 效能提升 — 人力成本

人力成本受开发效率影响,效率越高,一个需求需要的人力成本就越低;影响人力成本的原因有很多,解决方案这里不继续展开,简单列举几个会影响到人力成本的因素:

  • 软件复杂度

不合理的架构设计,以及拥有很长时间历史包袱的应用,由于其代码的复杂度越来越高,会让开发人员的开发效率明显降低,要定时对应用中的代码进行重构,增加可读性。

  • 测试 & 回归

作为开发过程中的重要一环,为了降低故障频率,自测往往占据了比开发更长的时间,因此提升自测的效率和准确度尤为重要。

  • 工作流程

不合理的流程也会拖慢工作进度,如工作分配不合理,责任互相推诿等;对工作职责的细分没有明确的定义,或者对于问题的推进没有严格的流程和产品化的工具,是这个问题发生的核心原因。

② 资源管控 — 技术成本

技术成本主要分为两类:

  • 计算成本

以内存运算为主,如容器、计算型中间件、外部平台等,往往流量越高则产生的计算成本越高,因此管控计算成本可以从链路、性能优化上入手,让同等流量下所需要的算力降低。

  • 存储成本

DB等偏重于存储的中间件,存储的数据越多,占用的磁盘空间越大,存储成本则越高,因此管控存储成本可以从数据治理入手。

计算成本与存储成本并不是完全分离开的,举例缓存,空间存储等中间件,往往是计算(读写操作)与存储并存,那核算成本的方式以长板为主。

在成本缩减中,技术成本占的比例是最高的,如何帮助缩减掉业务增长时疯狂扩张的成本,也是稳定性同学的一个重要课题。

5)数据治理

与数仓领域的同学不同,稳定性同学很少会对数据质量去做管理,这里提到的数据治理,主要是指治理一些会影响到稳定性情况的一些数据。比如,某业务发品时,由于逻辑没有对齐,有些情况下虽然发品成功,但是会认为发品失败,会不断进行发布重试,一直失败一直重试,也没有设置重复上线,导致同样一个商品最多发了上百万次,使线上某核心链路查询货商关系时大量full gc。

一句话总结:由于链路不合理、黑灰产、外部胡乱操作或线上问题产出的阻塞链路、扩大成本的大数据内容,都算作线上不合理的数据治理范围,每年固定的时段,稳定性同学会统一对这些数据做一次治理,降低成本,提升链路稳定性。

3、一个稳定性同学需要的能力

来打个比方,业务同学好比前线打仗的韩信,攻占地盘,为公司创造业务价值,而稳定性的同学则是维护大后方的萧何,为前线的同学提供保障,维持系统的稳定运行。如果业务发展不好,则公司无法维持好经营,但是如果前方断粮,系统的性能和稳定不足以承载这么大的业务体量,那么无论业务再怎么发展,都是白费功夫。保证系统稳定安全的运行,是稳定性同学最重要的工作。稳定性的工作强度很大,同时对人的心、脑、体考验也极大。它需要多元能力:

1)合格的技术能力

衡量一个稳定性同学是否能cover住垂直域稳定性工作的第一个重要指标,就是他的技术能力,对于技术能力要求的细节。日常要保持一直学习的心态,养兵千日,用兵一时,不能临时抱佛脚。在此我不做过多描述,这里只放一张关于java基础核心能力的图供大家感受一下:

2)临危不乱的心理素质和强大的身体素质

从事稳定性工作,不论与你是否有关,相关业务是否了解,遇到的所有问题及故障永远都是第一处理人,因此见到的问题故障会比一般同学多出很多,同时集团对于故障处理的要求非常严格,这时候就需要你有强大的心理素质。身体素质自然不用多说,如果说稳定性是业务发展的“1”,那么强壮的身体则是稳定性同学需要的那个“1”。

3)熟能生巧

如果说技术能力是排查问题需要首要条件,那么熟练度则检验了一个稳定性同学是否足够老成;一个问题新人定位&处理可能需要几个小时,但是成熟的稳定性同学凭借经验和工具可能瞬间定位到问题的根因,确定解决方法。

4)拉通 & 人际交往能力

稳定性同学大多都会参与到横向任务,如大促保障、跨域稳定性专项等事情中来,因此,优秀的人际交往、协调,拉通的能力,也是稳定性同学需要拥有的,与其他团队紧密协作、积极配合,也会为自己和团队留下较好的口碑,以后推进其他事情也可以事半功倍。

二、稳定性体系建设

1、防线建设

1)架构设计

稳定性工作本身偏向于底层技术,对于小、中公司而言,稳定性同学的定义更偏向于“技术架构师”的角色,所以底层技术架构上的设计是稳定性防线建设的一部分,简单举几个例子:

① 容量评估

什么情况下需要进行容量评估?我理解有以下两种场景:

  • 新发应用

应用建立之初,需要根据预估上游的流量,计算容器、中间件的吞吐率,在计算结果的基础上加上一些兜底的机器后,给出应用所需的容量。

  • 业务变化较大

当上游或者应用内部有较大的流量或性能变化时,要调整之前的容量,如大促期上线下线,或业务链路有重大迭代变更时。

容量评估是架构设计中比较重要的一环,容量太多会浪费成本,容量太少则会对线上可用性产生影响。

② 部署架构 & 容灾

在分布式系统大行其道的今天,容灾的场景基本在集团每个应用中都可以见到,比如集团的多单元部署,现在比较常见的架构主要是由中心A地(中心 + 混部集群)和单元B地(单元 + 混部集群)两个比较大的单元构成的,也就是所谓的“两地”,流量从入口端进行转发。

容灾的重要性不言而喻,如果单纯在一地做集群化,若遇到天灾人祸等不可避免的物理损失,将会导致服务不可用,事实上也经常出现某单元由于网络运营商的问题导致服务挂掉的情况,这个时候就可以通过从入口处切换跨地调用来解决。

虽然多地部署的理论比较简单,但是部署架构的一个重点在于将流量按照不同的作用去划分分组,如上图中的读、写流量分组是分离的,且读、写按照不同的上游业务也有单独拆分分组,这样就可以保证不会因为上游某一个大业务出问题导致整个集群不可用的场景出现。

当然,每个应用所面临的场景是不同的,那么如何部署、如何容灾,也是这个垂直域稳定性同学需要考虑的问题。

③ 数据一致性保证

当今的分布式系统,设计时绝大多数都会碰到异步链路,不管是业务上需要异步的去处理数据,还是中间件的数据同步机制,如果涉及到异步那就有可能会出现数据一致性问题,这与高可用问题分别是两个方向,但是他们两个本质上一样重要,甚至数据一致性出现问题产生的影响、恢复的难度要远大于高可用问题。

所以,在系统架构设计之初,就要做好数据一致性的保障措施,完善对账机制,并通过建立的防线发现存量和增量的问题。每个域面临的数据一致性问题场景不同,对于偏数据存储的部门,往往无法完全厘清模型与模型、数据与业务之间的关系,因此防线总会有疏漏,而一旦数据出现问题,往往是最难解决的:

  • 历史数据提取困难,如果没有数据留痕平台,只能通过数据离线表拉取,会导致数据可能有一定误差,如果故障时间线拉的很长,数据的提取会更加困难。

  • 复杂的业务逻辑,往往让人不知道该如何回滚数据,一旦回滚逻辑出现错误将直接导致二次故障。

整个数据一致性问题是一个非常大的专题,这里只是让大家稍微有一些体感,想要聊透这个问题需要很长的篇幅,在这里先放一张之前总结的资损防控方法图,供大家参考:

2)监控体系

我认为监控体系的建立是稳定性防线体系建设中最重要,也是难度最大的一环,线上的系统每天都处于不断的变化中,这种变化既来自自身的应用迭代,也来自上游业务的不断调整,随着时间的发展,业务的复杂度会变的越来越高,这时候就需要一个非常完善的监控机制,能帮我们快速预防和发现线上问题,如果没有一个好的监控体系,那么维护系统稳定性根本无从谈起。

虽然说起来简单,但是要实际建立一个完善的监控体系却是一个非常之难的事情,即使现有的监控体系非常完善,但是随着时间的不断推移,现有的监控必然会随之腐化,重新完善整套监控体系需要投入很大的人力成本(比如人员流动后,原有监控的运行体系没有交接,可能需要重新编写等)。

如何去建立以及维护一套完整的监控体系,其中的方法比较细节,在此列举几个我认为比较关键的内容:

① 监控覆盖面

覆盖面是评判体系是否足够优秀的第一个标准,对于业务特别复杂的接口,覆盖面越大,发现问题的概率就越高,但是对于历史包袱较重或业务比较复杂的系统,覆盖面做到百分百是不可能的,这里我从增量和存量两个角度讨论一下如何提高监控覆盖面:

  • 存量

梳理业务模型,盘点所有链路,优先从重要链路,例如从能影响线上流程或导致资损的链路开始,存量的监控盘点是一个持续不断的过程,随着时间的推移,我们的努力会使监控链路不断完善。

  • 增量

相较于存量,增量则更好处理一些,新业务上线时是否需要监控,可以通过CR或群体评审来决定。

其中,可能有的存量问题链路较难发现,或短时间内影响面较小,导致无人关注,或者一直梳理不出来,等到某一天问题积压爆发,这个问题在重存储的系统中非常明显,我们正在讨论一种解决方案:数据聚合分析,即从数据共性角度,判断出非法数据,进而判断出非法链路。

② 降噪 & 健康度

降噪是在监控中最让人头疼的一环,估计很多同学都有过体会,大多数情况下,线上告警出的问题并不会影响线上稳定性,这种告警一旦过多,容易让人逐渐放松警惕,当真正出现重大故障时往往不能第一时间发现。告警的有效性,就是我们常说的“监控健康度”。

很多成熟的监控产品,会将监控健康度作为一个重要的指标,当监控的告警有效性很低时,会停用监控先进行维护,关于如何进行监控降噪提高健康度,我个人经验有如下几点:

  • 提高维护效率

一个复杂的系统往往有很多的监控,每种监控可能都处理不同的业务,如果全部依赖稳定性同学进行处理,显然是不可行的,应当将监控按不同的业务维度分发给团队内的同学,避免出现一个人处理一大批监控,最终处理不过来导致告警积压,告警效率降低。

  • 及时降噪

明确分工之后,一旦监控发现告警,对应的负责人要及时处理,一般来说,需要人为check的监控告警积压数量不能超过20条,一旦超过就会极大的降低维护人员的工作效率,这种情况下要及时沟通,联系团队内其他同学安排时间协助排查;当发现需要降噪的数据时,要及时更新过滤规则,保证监控正常迭代。

③ 定时统计 & 复盘

团队内部要针对现有的监控进行定期盘点,健康度过低的监控要及时分析原因,并判断是否可以继续启用,不合理的监控关掉,避免混淆视听和增加监控成本。

3)流程规范

在日常中,相信大家不难发现,一些大故障,往往都有几个共性:

  • 一把梭

绝大多数大故障的特性,这种问题常发生于配置推送类的操作,比如很多同学为了图快,直接通过预案直接推送配置,或代码中有推送配置等,也有在变更发布中,没有认真评估好变更的风险,灰度批次较少导致大故障,换句话说,灰度的批次和时间越长,导致大故障的概率就越低。

  • 疏忽大意

发布时没有关注系统核心指标,虽然说灰度可以避免绝大多数的重大故障,但有些重大问题如果在灰度没有及时发现,等接近全部完成时爆发出来的话,本质上和“一把梭”没有任何的区别,这种情况常见于很多小流量应用中,即使一批机器也能扛起全部的流量,如果前面几批都挂掉了,除非看大盘,否则不会有任何的感知,但是最后一批发完之后,就直接报大故障了。

因此,严格的流程规范,会帮助我们及时发现和避免很多本不应该有的故障,当前阿里集团的安全生产团队已经将常见的几乎所有变更流程都进行了管控,内部如Aone、ChangeFree等平台已经进行了严格的平台化的规范,只要遵循线上正常的发布流程并加以防范,基本上不会出现特别大的故障,简单说一下我认为比较关键的几个流程:

  • Code Review

CR想必大家都做过,但是不应该只局限于“Code”,任何会在线上产生变化的变更,都应该有人Review,但是这一步过度依赖人为,虽然有一些代码静态分析的工具,但是由于业务场景的复杂性,这一步虽然不能完全做到100%的准确,但是仍可能发现一些风险和规避一些低端的问题,同时,有经验的同学可以从底层代码优化和建模的角度,降低应用的熵增速度。

  • 测试回归

靠人工的check无法达到太高的准确度,那么就需要靠平时测试同学积累起来的测试用例进行回归,测试用例需要平时不断的维护、根据业务变化不停的迭代,才能保证回归的准确性;同时,测试回归也是与测试同学进行对焦,从不同的视角上去发现问题,这也是集团要求发布变更前必须经历的一个阶段。

  • 严格审批

审批本身也是起到一个“知会”的作用,例如在大促期,紧急变更需要审批到大队长,也就是这个意思,老板和横向PM具有更广阔的视角,需要让他们判断变更的风险性以及当前是否有必要进行变更。

  • 卡点 & 灰度

上述的每个阶段,都必须通过产品化进行卡点,如果不通过则不能发布。

每个应用根据自己不同的情况都会有不同的卡点,不同的应用可能有自己的卡点平台,这些也可以通过对接Aone集成进去;至于灰度发布,大家都很熟悉了,这里就不展开讨论了。

4)混沌工程

建立完自认为完美的防线之后,肯定需要校验可用率,但是总不能通过等着线上出问题来检验防线是否生效,这样成本就太高了,此时就需要引入混沌工程,相信大家应该都很了解混沌工程了,那么就在这里贴一下相关的定义:

混沌工程,是一种提高技术架构弹性能力的复杂技术手段。Chaos工程经过实验可以确保系统的可用性。混沌工程旨在将故障扼杀在襁褓之中,也就是在故障造成中断之前将它们识别出来。通过主动制造故障,测试系统在各种压力下的行为,识别并修复故障问题,避免造成严重后果。

混沌工程在阿里集团内部的体现为故障演练,基本不需要部门内部自行操作,比较出名的有每年集团都会举办的红蓝演练,以及日常经常发生的生产突袭、断网演练等。

故障注入的平台,演练时一般使用集团内部比较出名的MonkeyKing,具体的使用方法这里不表,市面上有很多开源的混沌工程平台,原理都是类似的。

① 问题分类

针对不同种类的问题,有不同的注入和恢复机制 ,不详细展开了,上一张分类比较好的大图:

② 演练机制

整个故障演练机制分为四个部分,基本上也是所有混沌工程的思路:

  • 准备

可以在这一阶段做一些故障演练前的准备工作,保障我们的系统以及监控在故障演练之前是处于一个稳定的状态,比如说在执行演练前自动检查一下机器的状态,应用的状态,甚至说故障演练的agent是否已经部署到了对应的机器上等等。

  • 执行

在执行阶段可以选择你需要的故障场景,mk2里面支持像不同的应用注入故障,也支持同时像一个目标机器下发多个故障,故障的场景也不局限于mk平台提供的故障能力,用户自己开发的故障能力也可以集成进来。

  • 验证

检查阶段就是进行故障执行后的一些状态检查,检查的范围包括了系统本身的一些指标,比如我是CPU满载,那么CPU是否真的满载了。

  • 恢复

我们希望每个故障场景都是可以有相应的恢复手段的,如果故障注入后,开发人员没有办法在一定时间内处理故障,那么平台本身一定要保障故障是可以恢复的。

2、快恢机制

即使防线建设做的再好,但是人难免会有疏漏,不存在能百分之百拦截故障的防线,如果故障已经发生,那么当前的重点就应该是快速止损并恢复。

从发现、处理到复盘,阿里集团有一套完整的SOP,整个处理流程非常的规范,同时,阿里集团对于高可用故障恢复的时间要求非常高,一般来说是1-5-10,即一分钟发现,五分钟止血,十分钟恢复,不过肯定不是所有的故障都能严格达到这个高标准,但是处理速度当然是越快越好,避免故障升级。

那么下面就从定位、止血、恢复这三个阶段来讲述一下快恢中具体要做的事情:

1)快速定位

很多同学第一次面对问题或者故障时,往往头脑空白不知从何查起,如果碰到大故障时,很多主管在后面围观,心情则会更加紧张,进一步拖慢了查问题的时间,那么如何对线上的故障和问题进行快速定位呢?

首先,在定位问题之前,要快速的确认是不是属于本域的问题,很多时候问题的表象看似出自于自己的应用,但实则可能是上下游、中间件或者硬件问题引起的,如果方向错误,可能会拖延故障的处理时间,放大线上影响和故障等级,那么如何快速定位,我认为可以从变更的角度去入手思考:

本域是否发生过变更?这个是最核心的判断因素之一。

如果没有,那很大可能跟本域的关系不大,请注意,这个变更不仅仅是通常理解上的代码发布、配置推送、数据操作等,而是所有可能会对线上的运行环境产生影响的操作,如代码中的配置推送,上下线或置换容器等;当然,并不是说没有变更就完全没关系,有些情况也有例外,举几个常见的例子:

  • 属于定时任务、延时执行等变更后一段时间才运行的链路。

  • 由于流量评估不准,平时流量较少,但某一时间段峰值流量突然剧增的链路。

  • 上线前测试不足或上线后流量较少,业务覆盖面不全的链路,可能由于突然的冷门流量导致报错。

本质上来说,这些情况产生的错误还是由于“变更”引起的,只不过是变更生效的时间被延后了。

如果发现存在变更,那么要结合大盘,判断故障的时间线是否与变更的时间线吻合或相差不大,如果是的话那么就八九不离十了。

在定位到产生问题的域后,如果不是自己的问题,那么可以尽量协助排查,如果是域内产生的问题,那么就要着手开始定位根因,这个时候就是考验稳定性同学的基本功和经验了,同时也要结合集团给出的一些比较好的产品化工具,例如:

① 监控大盘

常见的监控系统有很多,一些开源的监控大盘让我们面对大多数问题时基本不需要去机器上命令行排查了,对于不同的场景,用对了监控可以事半功倍。

阿里内部有各种各样的大盘,可以让集团的同学在处理问题时的速度更快,同样部分开源的大盘也非常强大,至于如何做产品选型,大家可以自行评估,思路大概就是如下几种大盘:

  • 硬件 & 中间件指标大盘

从容器硬件水位、中间件(RPC、缓存、DB…)水位等偏重于技术指标的大盘中,通过时间线定位出问题的大致方向和时间线。

  • 链路追踪大盘

以传输协议、接口作为维度,找出相关的链路和trace,具体问题具体排查。

  • 流量调度系统

偏重于单机大盘的系统,可以从秒级维度查出单台容器的性能指标,并可以实现流量调度,将有问题的容器流量摘除。

② 分布式日志系统

对于一些代码层面或业务层面的报错,单纯通过大盘进行深度定位是不现实的,究其根因还是要到底层去查日志报错堆栈,这个时候就需要用到分布式日志系统了,通过分布式日志系统采集的信息,可以配置相应的大盘,或直接搜索错误堆栈,进行细节上的排查。

2)快速止血 & 恢复

之前将问题划分为高可用以及数据问题,那么也按照这个分类来讲一下对应的止血 & 恢复策略:

① 高可用问题

止血与恢复在高可用问题上,大多数情况是相关联的,止血即恢复,如:

  • 某系统变更导致应用夯死,回滚重启的同时,系统恢复正常,达到了止血和恢复效果。

  • 推送某开关,导致业务链路阻塞,回滚开关后,链路恢复正常。

  • 由于网络服务商原因,导致某地域的机房网络重传率过高,通过切流其他单元达到了恢复止血。

同时,相信大家都接触过高可用问题,对于这类问题的快恢也有一定的了解,限于篇幅原因这里就不再一一描述不同高可用问题的恢复策略了,直接在这里引用和拓展一下之前总结过的高可用问题快恢六招:

  • 切流:遇到天灾人祸等不可避免的地域性故障,应对单元维度,机房维度,机器维度切流;业务层面上要提前布防,通过集团提供的diamond、switch等配置中心进行代码熔断。

  • 扩容:流量暴增时对集群进行扩容,适用于流量超出预期的场景。

  • 限流:接口限流可以从入口层面保护绝大部分流量,热点限流可以保障流程中涉及的中间件或者下游不被打挂。

  • 回滚:较为直接的止血方式,回滚前需先机房隔离或切容灾,防止回滚时间较长升级故障。

  • 降级:若是链路弱依赖,先降级再排查。

  • 重启:应对内存溢出,fullgc连接数满等。

② 数据问题

数据问题与高可用问题有非常大的差异,高可用问题恢复起来较为简单,通常有比较明确的策略,但数据问题则不同,我将其分为两类:

  • 数据计算错误:由于线上逻辑问题导致数据计算错误,进而阻断链路或产生脏数据。

  • 数据存储错误:持久化与非持久化的数据存储内容与期望值出现偏离,如商品价格落库错误、缓存数据错误等,导致链路上读到的都是脏数据,产生数据不一致或资损问题。

其中,数据计算错误的恢复策略较为简单,可以直接通过熔断、切流等机制关闭增量问题来源来进行恢复止血,数据问题真正的难点在于存储错误,非持久化的数据存储,如缓存,可以通过熔断增量问题入口,清除存量数据来解决,但是一旦持久化的数据脏掉且量级非常大的话,从数据的提取到数据的回滚都非常的困难:

  • 数据提取

  1. 量级大:在很多情况下,回滚数据需要提取非常大量的数据,提取速度很慢。

  2. 复杂程度高:模型比较复杂的系统,提取数据时需要非常复杂的过滤规则,且经常出现提取到一半时发现过滤规则有问题的情况,这时候之前提取的数据就无用了,进一步加长恢复的时间。

  3. 数据实时性:如果没有数据留痕系统,那么提取数据最常见的方式就是从ODPS中捞取,即天表或小时表,但是这两种表都会有数据延迟,即从产出数据表的时刻起,到当前的时刻为止,如果数据发生过变化,那么离线表中是无法获取到的,也就是从离线表中拿到的是脏数据,会导致一批数据回滚不准,产生二次故障。

  • 数据回滚

  1. 风险高:提取出的数据如果不准,回滚将直接出现二次故障,进一步加大数据回滚的难度。

  2. 性能问题:当回滚的数据量过大,需要一个产品化程度比较高的数据订正平台做控速、灰度控制、失败重试以及进度管控,否则订正速度一旦过快,可能直接击穿链路节点。

因此,数据存储问题或我们常见的资损问题,往往主要关注的不是恢复时间,而是主动发现率、止血时间、资损金额等,因为要快速恢复量级很大的数据存储问题是不现实的,往往都是依赖人为提取数据以及手动恢复,事实上针对数据存储问题,也没有系统能做到通用化的数据回滚策略,因为每个业务、每个系统的提取数据,回滚数据的逻辑基本都是不同的,如果依赖平台通用逻辑回滚,那么二次故障的概率会非常高,所以说,对于数据存储问题,要做到第一时间通过熔断、切流等机制止血后,在优先保证数据绝对正确的情况下,再进行回滚恢复,不能盲目的追求恢复时间。

3、反哺

1)复盘 & Action 跟进

每一次故障都是血的教训,但是以我的视角来看,发生故障并不完全是一件坏事,因为应用系统是人造就的,是人就一定会犯错,所以系统也不可能保证百分之百的强壮,有问题则证明系统、流程还有不足,才能推动我们不断的向前进步,这也是我们每一次故障之后要进行复盘的原因,犯了错并不怕,重要的是如何改正。

集团对于故障的复盘有一套严格的执行流程,大概如下图所示:

具体详细的复盘流程不详细展开,谈谈我认为复盘这个节点比较重要的几个问题:

① 三省吾身

无论是自己,亦或是团队其他同学导致的故障,一定要问自己几个问题:

  • 为什么:背景是什么,故障是怎么发生的?根因是什么?为什么当时没发现?

  • “我”:

  1. 就是我:这个故障是我导致的,我当时怎么处理的这个问题?恢复的快不快?还有没有可以改进的地方了?

  2. 如果是我:他这次产生的故障,如果放在我身上,我会不会跟他做一样的事情?如果要我来恢复,我应该怎么做?

  • 下一步:这次的故障暴露了什么问题?是代码bug还是流程问题导致的?我可以给团队提什么样的建议来解决这个问题?

  • 动手去做:确定解法,我可不可以帮助团队同学去做完这件事情,会对我自己有多少成长?

② Action 落实

很多时候,我们都只局限在“这一次”的故障中,而不会去思考“每一次”。在我看来,Action真正的作用,不只是为了单纯的解决这一次的问题,而是要我们举一反三,从根因上思考,系统中是否还存在与这次故障相同的问题?我们要如何分类的去解决,这样才能真正的将这一次故障的效应和Action发挥最大的作用。

2)稳定性分享

除了稳定性的技术建设,文化宣导也是基础建设的一部分。

除了故障方面,稳定性同学所做的底层优化专项等偏向于技术层面的工作,也可以在团队内部或跨部门做分享,建立工程师文化,培养技术兴趣,以及扩大部门和团队在集团中的影响力,以我所在的商品团队举例,每月都会举行一次“工程师之夜”的分享会,包含技术、业务模型等比较有代表性的工作成果,同时团队内部优秀的同学也会经常跨域去做技术分享。

三、后记

稳定性工作远比文章里的内容要复杂的多,每一个单点拉出来,都能形成一篇文章去介绍,限于篇幅问题,无法将稳定性所有的内容表达出来,这里将我过去几个月的思考和大家分享,欢迎一起交流评论。最后,也向所有从事稳定性工作的同学致敬,希望各位都能在其中获得自己想要的成长和收获。

>>>>

参考资料

  • 面向失败的设计-故障与攻防演练锤炼容灾应急能力

    https://developer.aliyun.com/article/726337

  • 知乎:什么是混沌工程?Answer:亚马逊云科技

    https://www.zhihu.com/question/308294657

  • 天启回归提效与精准测试

    https://developer.aliyun.com/topic/n-cases?id=115120

作者丨清寰

本文来自博客园,作者:古道轻风,转载请注明原文链接:https://www.cnblogs.com/88223100/p/How-to-Improve-Vertical-Domain-Stability.html