暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

关于线上变更的一点思考

入境繁华 2020-03-01
1086


中间件是作为整个技术体系的底层部分,一点点的错误都将引发严重的故障。在中间件从事研发工作,见过身边发生的一些故障,也亲身经历过几个故障。正因为中间件是底层部分,任何细小变更都得注意。即使是从事业务开发,一些细小变更也会引发资损、严重舆情、故障等等。所以在变更时,一定要心怀敬畏,谨慎行事。今天总结下关于线上变更稳定性的一些思考,从开发者的角度看如何警惕风险,避免出现线上故障。





线上变更三板斧


蚂蚁金服 Service Mesh 深度实践 提到,蚂蚁内部使用“线上变更三板斧”, 这里的变更,包括发布新版本,也包括修改配置。



线上变更“三板斧”指的是:

可灰度:任何变更,都必须是可以灰度的,即控制变更的生效范围。先做小范围内变更,验证通过之后才扩大范围;


可监控:在灰度过程中,必须能做到可监控,能了解到变更之后对系统的应用。如果没有可监控,则可灰度也就没有意义了;


可回滚:当通过监控发现变更后会引发问题时,还需要有方法可以回滚;


(以上定义来自 蚂蚁金服 Service Mesh 深度实践  )


这些原则在我们日常开发和运维过程中都值得借鉴,可以减少故障发生。今天从 蚂蚁金服 Service Mesh 深度实践 提到的三板斧,做一个思考。

更多关于三板斧介绍参考


01 线下和灰度充分验证 

可灰度说的是对任何变更都可以通过灰度验证。这里需要关注三点:

  • 对老系统影响的灰度。新的变更发布到少量灰度机器以后,是否可以验证到对已有功能造成影响。

  • 对新变更的灰度新的变更通过灰度验证功能是否OK。

  • 新老板版本兼容性问题。新老版本同时在线,是否兼容呢。


第1点要求我们,需要有一套系统自检机制或清单,哪些指标完成以后说明老版本系统(未发布的那部分机器)是正常的。不能简单根据系统进程启动成功,没有错误日志来判断。日常开发时,很多系统都是靠经验,靠人肉记忆来检查各个系统点。而人的状态是不稳定的,因为加班发布,疲惫导致疏忽了某些步骤。


所以我觉得,系统是有一套标准的检查清单,并将这些清单尽可能自动化。类似飞行员在起飞前对照飞行员手册和checklist 检查系统,避免遗漏。对于系统而言,也可以通过列清单,将发布的每个阶段梳理出来,每个阶段应该检查什么。比如灰度发布时,需要关注哪些指标,哪些指标完成,完成的时候打个勾。打勾是避免短时记忆导致某些被忽略了,保证每项都检查到位。这个过程最好时 double check 机制, 一人根据清单检查。一些大公司也具备了自动化机制来自检,也可以避免人为疏忽。


第二点。有些系统或功能很难通过单台去验证,甚至不容易验证。比如高可用性(一般需要kill 部分机器验证),不能随意去模拟机器宕机等场景,容易引起线上故障。这部分则要求我们在线下做好充分的验证。但是有时候验证的时候我们往往会忽略一些点,也忘记了哪些点验证到。就像之前一个前辈和说的,写代码的时候脑子里要想到,写了这个功能甚至这行代码,我应该怎么去验证,把验证点都想好。将这些验证点列成清单,一项项验证。这些项可以通过单元测试或集成测试来覆盖,如果一些复杂场景则通过线下模拟验证。


为了验证充分,这就要求我们时刻提醒自己:这个功能,甚至这行代码。对现有系统有什么影响?如果出错了可以通过什么方式监控、观察到?如果出了问题是否有快速恢复或关闭的方式? 


是否对现有功能有影响?这个则需要要求我们对现在改动的代码或系统很熟悉,了解整个架构和设计理念。需要将改动代码的上下文、生产者和消费者、整体链路梳理清楚。比如改了一个字段,哪些地方使用了这些字段。使用了字段的方法又被哪些地方调用? 通过逐层分析,确定判断对系统是否有影响,避免一个细节修改引起蝴蝶效应,导致集群故障。


第三点关注新老版本兼容性。灰度发布过程中,关注新老版本代码是否兼容,也是 checklist 的一项指指标。这个也是大家比较容易忽略的。


02 配置监控告警

一般公司都提供了监控平台,开源的监控平台有 cat 等。没有监控就像在夜里走路,一片蒙黑,一旦出现问题只能被动感知。监控配置比较理解容易理解,简单理解就是对系统变更后的行为进行监控。这里也分为两部分:

  • 对老版本代码的监控。这要求我们能够将系统的健康指标梳理并配置到监控系统中,一旦发生影响就能实施监控到。

  • 对新代码的可监控。新代码上线以后,我们怎么观察新代码是OK的,哪些指标出现异常就需要立即做应急手段。这个则需要在写代码的时候做充分的思考,哪些场景下需要打上日志来配置监控或直接监控埋点。在这里不仅考虑新功能对自身系统的影响,还得考虑业务出现不符合预期时也能被监控到。


03 做好随时应急准备

大部分应急变更里的应急手段就是回滚,但对于一些系统来说回滚会引起集群变化,也会导致一些不可预期的问题。这种应急是整个代码版本层面的应急手段,这种手段在发布过程中可以有效解决。


但是存在一种情况,一个新功能上线后一段时间线上代码逻辑还是没走到,系统又有几个新的版本上线了。这个时候该功能发生问题时就很难回滚处理了,回滚成本很大。新的功能有必要增加一些动态开关,做到动态可插拔的方式,一旦发生问题就可以及时开关关闭,功能不生效





心怀敬畏,谨慎行事


根据墨菲定律,有一定概率发生的事情就一定会发生线上故障一样,不要以为这个事情不会发生在自己身上,就放松警惕。所以任何一个功能的添加,都需要心怀敬畏,谨慎行事


  1. 写代码的时候脑子里要想到,写了这个功能甚至这行代码,我应该怎么去验证,把验证点都想好。 

  2. 不能聚焦当前改动的功能和代码行。写代码时需求对系统和上下游充分理解,对系统架构和设计理念充分理解,才能知道一行代码对系统是否带来蝴蝶效应,导致集群故障。

  3. 灰度阶段,系统需要有一套自检清单,发布过程像检查飞机系统一样,一项项操作、打勾。发布期间 double check

  4. 灰度阶段要兼顾老版本功能回归、新版本代码验证、新老版本兼容性。 

  5. 完善监控,新代码上线时也要考虑对自身系统影响的监控点,以及对业务影响的监控点。

  6. 可应急不能只考虑可回滚的场景,还需要考虑功能可以动态关闭。万一代码代码被覆盖多个版本后,可以通过功能开关关闭降低回滚到很早历史版本的风险。其实这个也适用于很多框架研发,不能写死功能,应该增加开关,让用户可灵活配置和选择。


这里给大家推荐一篇同学写的文章, 《保持敬畏,保持严谨》。文章里提供了三个建议,我觉都值得借鉴:

  • 开发人员必须做好充分的自验证。

  • 在权衡时间和质量时,优先考虑质量。

  • 一定要尊重流程。


更多:http://stillwaters.top/stay-serious/

文章转载自入境繁华,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论