社会焦点

依赖治理、灰度发布、故障演练,阿里电商故障演练系统的设计与实战经验

字号+ 作者: 来源: 2017-05-25

依赖治理、灰度发布、故障演练,阿里电商故障演练系统的设计与实战经验,图片转灰度图,电除颤故障应急演练,阿里农村电商,灰度图浮雕图,苏泊尔电压力锅故障

  依赖治理、灰度发布、故障演练,阿里电商故障演练系统的设计与实战经验

  作者|中亭

  编辑|小智

  2016 年,阿里巴巴研发了故障演练系统,把故障以场景化的方式沉淀到系统中,在线上主动回放故障,验证监控报警、限流降级、故障迁移、容灾策略、故障处理的有效性。本文将探讨经典的故障类型,剖析故障成因,提出解决方案,介绍故障演练系统的设计和演进,提出故障演练的原则和经验。

注:本文整理自阿里技术专家中亭在 QCon 北京 2017 上的演讲,由阿里技术公众号授权转载。

  写在前面

本文分享的内容主要还是围绕故障治理有关。众所周知,故障治理本身就是一个比较大的话题,几乎涉及到运维、研发、故障运行管理的全部岗位,奇葩一点的故障还可能涉及到运营和产品经理。聊到故障的苦与泪,相信 45 分钟绝对连开头都没讲完。今天的分享,主要还是回归故障发生的本质,故障原因角度切入。看是否有一些方法论和通用性的手段可以沉淀出来。希望可以对大家有所帮助。

依赖治理、灰度发布、故障演练,阿里电商故障演练系统的设计与实战经验

首先介绍一下我自己,姓名周洋,花名中亭。2011 年加入阿里接触稳定性技术领域,开始做一些稳定性产品的研发,同时也会承担一些架构演进的推进工作,比如 HTTPS 改造,电商交易链路升配等。2015 年开始搞双 11 大促,做为共享事业部的大促负责人,保障了双 11 的稳定。也获得双 11 老 A 也就是双 11 特种兵的称号。

共享事业部对于在座各位可能比较陌生。如果我换一个说法,商品、交易、会员、优惠、评价、中间件,大家应该就都知道了,这是双 11 当天最具挑战的链条之一。右边是中间件核心作战室成员,在过了双 11 业务高峰后的一张合影。2016 年至今,工作的重点在常态稳定性的确定性方面,今天的分享也是主要围绕这部分内容。

  分布式系统常见依赖故障治理及技术演进

首先抛一个问题,什么情况下你会认为淘宝网挂了? 我相信关注这个问题的人很多,不过能给出确切答案的人并不多。因为这个看似简单的问题,真要回答起来好像也不是那么容易。今天的分享,我先试着给大家回答一下这个问题。

依赖治理、灰度发布、故障演练,阿里电商故障演练系统的设计与实战经验

让我们从一张“简单”的页面说起。这张页面叫做商品详情页,对于大部分人来讲,这张页面是他们在淘宝完成一笔订单的第一步。而商品详情页的使命就是把商品的信息没有保留的展示给大家,引起大家的兴趣,引导大家完成购买或是收藏。从信息展示的角度来讲,商品详情页确实是一张非常简单的页面。

依赖治理、灰度发布、故障演练,阿里电商故障演练系统的设计与实战经验

我们再来看一下商品详情页应用的后台架构。商品详情页是阿里最早实现静态化应用之一。那些与浏览者无关信息,比如商品标题、图片信息、销售属性组合等信息均直接进入缓存,其他和用户相关的,如优惠、库存、物流、服务等动态信息则通过异步调用方式填充至静态化后的页面框架内。为了在一张页面展示足够多可供决策信息,撩起用户的购买欲望,详情后台必须去依赖非常多的服务应用,聚合足够多的信息。少则几十,多则成百。从这个角度来讲,商品详情页面又是阿里依赖最复杂的应用之一。

互联网业务的一个主要特点是,业务迭代非常快,每天有新需求,每周都有新发布,每年都有大重构,每一次变化都有可能导致状况的发生。越是贴近用户的系统,受下游服务影响越大。那么我们不仅好奇,对于详情这个阿里最复杂的应用,下游发生一些状况时,系统会变成怎样?我们通过两个实验来观察一下:

  实验一:假设后端的优惠、库存、物流发生故障,我们来观察一下商品详情页的表现。

依赖治理、灰度发布、故障演练,阿里电商故障演练系统的设计与实战经验

乍一看,好像没什么问题。只是觉得页面清爽了一些。或许在这个信息过暴的时代,看着这么清新脱俗的页面,还有一点点暗爽。

在现场做了两个调查,观察大家对实验一的反映。调查 1 是请认为详情页故障了的同学请举手。结果是现场没有人举手(也可能是现场氛围还比较冷);调查 2 是请大家来找茬,前后两个详情页有多少处不同?这次有一个妹子说出了正确的答案(同时也向妹子赠送了电子工业出版社出版的讲述阿里双 11 技术演进的《尽在双 11》书籍)。

依赖治理、灰度发布、故障演练,阿里电商故障演练系统的设计与实战经验

没有对比就没有伤害,一共有 6 处不同。从功能角度,这铁定是一个故障页面。不过从用户体验和业务角度讲,少了这些信息也不影响商品购买,不影响核心用户体验。好像又是没故障?有点纠结,对吧? 您先纠结一会儿,我们来进行第二个实验。

  实验二:当商品详情的"商品"出了问题,商品详情会怎样?

依赖治理、灰度发布、故障演练,阿里电商故障演练系统的设计与实战经验

详情还是那个详情,只不过是商品详情变成了错误详情。第一张页面:很抱歉,你查看的商品找不到了。有可能是你访问的方式不对,比如 URL 上面少了一些参数,也可能是后台真的出问题,对于用户还算是比较温柔的一种方式。第二张页面:很可能就是网站真的出问题了。比较可能的原因是后台没有合理的处理超时导致前端异常。不过说实话,这个页面我也非常少的见到。如果真的出现了,那基本就是一次非常严重的事故。

依赖治理、灰度发布、故障演练,阿里电商故障演练系统的设计与实战经验

通过上面的两个实验,相信大家应该对于我们今天要介绍的一个概念"强弱依赖"有一些模糊的感觉了。 从感性的角度来讲,就是当下游依赖服务出现问题时,当前系统会受到一些影响,让用户有感觉的是强依赖,没感觉的是弱依赖。

不过这种定义不够严谨,因为总不能说没有用户访问时,就不算故障吧。所以也需要从理性角度定义一下:首先应该发生状况,其次应该是核心业务,最后是否带来损失。不影响核心业务流程,不影响系统可用性的依赖都可以叫做弱依赖,反之就是强依赖。

依赖治理、灰度发布、故障演练,阿里电商故障演练系统的设计与实战经验

终于解释清楚什么是强弱依赖,那么做好强弱依赖治理到底有什么意义?抛开依赖模型来看强弱,意义不大。严谨的依赖模型应该包括关系、流量、强弱三个组成部分。

依赖关系定义依赖的方向,我依赖谁,谁依赖我。流量定义着每个应用、服务、方法调用的次数,强弱则定义着依赖的松紧程度。依赖治理就是通过科学的手段持续稳定地拿到关系、流量、强弱的数据。强弱依赖主要可以被应用到下面的场景:

  • 系统改造验收:对于分布式系统,至少应该做到运行态中不会因为我依赖的系统出现故障,而引起当前应用出现可用性的问题,比如进程挂掉,频繁 FullGC,负载飙高等,何时何地都具备快速止血的能力。

  • 限流降级参考:对于弱依赖,一般都要配置限流或是自动降级策略,比起通过拍脑袋或是经验值来设定,倒不如通过实际的故障测试来进行微调,比如对于下游出现超时情况,就可以通过实验得出基于线程池限流到底要填写多少数值。

  • 应用启动顺序:理想情况下,应用启动更应该做到 0 强依赖启动。不过有一些情况无法做到。因此应用启动的依赖顺序也需要实时关注。特别是新 IDC、机房建站时,那个蜘蛛网一样的依赖关系,最好是通过系统方式获得。

  • 故障根源定位:后台系统的故障,往往通过上一层的业务故障表现出来。故障处理讲究的是争分多秒,良好的强弱依赖,对于系统自动化诊断有非常大的助力作用。

  • 依赖容量评估:正常调用链路下系统容量需要评估,当某个弱依赖挂掉时,整体的容量是否有变化。

  • 说完背景,终于可以聊一下强弱依赖的技术实现。在阿里,强弱依赖的技术演进整体上分了 3 个阶段,每个阶段的方案的诞生都有其独特的时代背景和业务难点。现在回头看来,也可以看到当时技术的局限性和突破。

    依赖治理、灰度发布、故障演练,阿里电商故障演练系统的设计与实战经验

    熟悉淘宝技术发展史的同学都知道,2008 年阿里刚刚完成一个代号为五彩石的项目,完成从巨石系统向服务化系统的改造。业务和开发模式上有了较大的发展,不过网状的依赖关系也带来了非常多的问题。这个纪元的主要特点是:故障频发,技术思路和方法都是以结果为导向,糙一点、结果精度差一点可以忍受。

    模拟依赖故障技术上有三招,改代码 + 发布,远程 Debug+ 重启,登陆机器去执行一些 shell 命令操作。 好处是灵活随意,可以一定程度达到效果;坏处是成本高,影响环境稳定,你测试的时候其他人处于无法工作状态,影响效率。此外,这个阶段,因为分布式链路追踪技术还没起步,所以模拟依赖故障时,经常会漏掉一些主机或某些服务。故障的粒度也比较粗,对于一些 Linux 的命令,都是主机级别的。

    阿里内部有一套日常环境,主要做上线前的集成测试。为了尽量减少对环境的影响。我们通过修改服务版本的方式,形成一个独立的测试环境。记得 11 年下半年,我开始做第一版的时候,我搭了淘宝 12 个核心应用的日常环境,踩坑无数,纯体力活,也算前无古人,后无来者了。

    通过这套环境跑了几次结果,发给核心的业务 TL,大家很兴奋,貌似找到一条治理的路子。不过很快暴露了新问题,比如环境的运维归属问题,开发机器的干扰问题,以及对于业务的了解程度和测试粒度问题,所以在很长一段时间测试的范围都局限在交易核心链路。

    依赖治理、灰度发布、故障演练,阿里电商故障演练系统的设计与实战经验

    第二个阶段的核心就是提效,从第一个阶段的痛点入手,解决人的成本和环境的问题。这个阶段之后,基本可以摆脱手工方式,效率上有大幅度提升。

    这个阶段也引入了一些测试技术,其中用的比较多的是 Selenium,通过这种技术可以提前录制用户行为并转化为测试脚本,并且每一个步骤都可以截图记录,方便问题复查。

    在这个时期,阿里中间件的技术有一定发展,分布式追踪技术出现,可以把用户访问的链条串联起来,排查问题的效率有了一定提升。同时所有的中间件,如 Nginx、消息、分布式服务调用、分布式数据库、软负载和配置中心等都做了改造,支持用户流量的标记、追踪和路由控制。基于上述这些技术进展,环境的问题就有非常大的突破。

    在内部我们称为叫二套环境。它的核心原理是在基础环境之上,动态区分出一些小环境,他们分别是某个业务的子集。项目之间彼此独立,不会互相调用,只有当依赖的服务不在时,才会去访问基础环境的服务。数据库和缓存是公用的。

    在这个阶段,我们不必再去修改代码的服务版本,每次发布后,代码的版本等能够自动化的保持一致,运维成本有所降低,野服务干扰的情况也有所缓解,人的介入非常的少。不过还是有一些问题亟待解决:

    首先,二套环境的路由策略是和用户绑定的,也就是说需要提前去做一些配置;其次,域名上也有一些限制,加了 second 等前缀,测试路径中 URL 等复用率低的问题没有完全解决;第三,测试的粒度仍然很粗,独占机器,规模化推广时,机器成本和用例运行的成本还是很高;第四,故障场景缺失,只存在于基础环境的服务没法模拟的故障,如:数据库故障,缓存故障等。

    依赖治理、灰度发布、故障演练,阿里电商故障演练系统的设计与实战经验

    2014 年的时候,我们的思维方式有了比较大的突破。我们不再纠结于环境和外部手段的改进,而是回归到强弱依赖关注最核心的部分。那就是业务影响和系统设计。能否实现一种只与代码设计和业务相关,而与外部环境无关的方案呢?

    这期间有两个关键思路或是推论:

  • 推论 1:我们要的是下游依赖出现故障现象,不必真的是下游服务提供方出现故障。只要消费方感觉下游出现故障即可。从这个思路来讲,商品详情如果要做强弱依赖测试,只要自己玩就 OK,不需要去折腾下游依赖的几十个应用。

  • 推论 2:我们之所以需要单独搭建环境,为的就是控制故障的影响范围。那么我们可以换一下思路,就是我们只影响要发生故障的请求,其他的业务流量都放过。是不是就可以达到目的。本质上是一种对业务流量的筛查能力。

  • 有了上面的思路,第一问题就是如何拦截用户的请求?拦截用户请求,让用户改造成本最低,没有什么地方比中间件更适合了。每个通用的远程调用接口,都是可以做文章的点,并且中间件之上的业务系统不用做任何改造。

    下一个问题就是故障规则和业务识别,我们曾考虑在用户请求的入口就打上标记,置入故障规则,不过发现对于 post 请求,异步 js 请求,定时任务等都有比较大的改造成本,且有安全隐患。 所以就增加了一个服务端,直接下发故障规则到依赖插件上。

    故障插件通过对流量的调用拦截 + 业务识别,唯一确定影响哪一个请求,然后通过故障规则判断是注入异常还是超时,从而达到模拟故障的效果。 因为插件可扩展的设计,所以我们默认是可以同时注入多种故障场景的,同时插件也会把影响到请求的详细信息异步上报给服务端做分析。

    理论上通过上述的方案,在业务流量输入方面,我们没有任何要求。无论是人的自发测试行为,还是机器的测试行为,都没有任何限制。只不过为最大限度复用已有的测试用例积累,提高自动化程度,我们设计了一套用例注解,封装了和强弱依赖服务端的通信。利用 Junit 生命周期的特点,完成故障规则的下发和清除。

    任何一个测试用例,20 秒之内改造成一个强弱依赖的测试用例。在结果输出方面,会详细的展示一次强弱依赖检测的过程,以及测试用例涉及到的链路的依赖变化。到此阶段,强弱依赖真正达到了一个相对里程碑的版本,2014 年开始,强弱依赖也作为双 11 必做的一个横向项目。

    下面是强弱依赖注解和依赖系统的示例:

    依赖治理、灰度发布、故障演练,阿里电商故障演练系统的设计与实战经验

    依赖治理、灰度发布、故障演练,阿里电商故障演练系统的设计与实战经验

    总的来说,整个强弱依赖技术演进历史,就是对数据准确性,稳定性,成本、效率的不懈追求,并在这几者之间达成一个动态平衡。

    转载请注明出处。


    1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

    相关文章