速来报名!AICon北京站鸿蒙专场~ 了解详情
写点什么

服务变更如何做到高可用?

  • 2019-08-07
  • 本文字数:3527 字

    阅读完需:约 12 分钟

服务变更如何做到高可用?

近期,Cloudflare在更新 WAF 配置规则时,因其中一个规则包含了正则表达式,导致 Cloudflare 全球机器上的 CPU 峰值使用率达到 100%,在最糟糕的时候,流量下降了 82%,对整个互联网都产生了明显的影响。


因此,变更的定义,不仅仅是狭义的上线新版本代码,也应该包含配置变更,数据变更,操作系统变更,网络变更,基础设施变更等方面。变更是运维人员的主要工作内容,同时也是导致服务故障的主要原因。据 Google SRE 统计,线上 70%的故障都是由某种变更而触发的。

服务变更的关键点

部署清单

部署清单主要是管理部署期间的整个生命流程,通过将各个阶段的各个步骤进行罗列和长期维护,从而逐步形成针对特定变更场景的说明手册。


如果只是升级一台服务器的二进制代码,需要部署清单吗?答案是肯定的。不能把二进制代码变更等同于二进制文件替换,在替换动作之外,有很多的工作内容,仅仅是更新完毕以后,就需要考虑如下问题:


  • 程序是否正常启动

  • 日志是否存在异常信息

  • 服务功能是否正常

  • 服务性能是否符合预期

  • 服务关键指标是否异常


对于多模块,多系统,多团队配合的变更操作,如果没有一份事前经过充分验证的部署清单,谁在什么时候应该做什么事情,准入条件是什么,交付标准是什么,有哪些操作禁忌和注意事项,那这种复杂变更的结果就只能靠运气了。


随着运维自动化水平的提升,部署清单并不会消失,而是在载体上有所不同,从早期的纸质上线单,到现在内置于部署系统中,实现了更好的经验传承,校验完善,流程管控,信息分享等。

灰度发布

绝大部分服务,都不应该由单个实例组成。那么,在变更的时候,就应该避免一次性升级所有实例,而应该分批次的逐步升级,并在每个批次间预留一定的时间间隔对上一批次进行观察和评估,从而决定是否继续进行升级,以此来保障变更的质量。


以 Google 为例,其灰度发布的比例,从 0.1%开始,每 24 小时增长 10 倍推进,从 0.1%-> 1% -> 10% -> 100% (详见 Google SRE 中文版 162 页),并且灰度的初始比例一定不可以超过服务整体的冗余度。同时,在对服务进行变更操作的期间,需要将流量摘除,避免对线上产生影响,变更操作完毕后,方可引入灰度流量进行验证。


在灰度阶段,有针对性的选择灰度流量,尽可能完整的覆盖各类业务场景和用户类型,并通过流量调度形成局部热点,对服务的性能进行验证,避免全量上线可能出现的性能下降。

快速回滚

变更操作一定要有回滚预案,并能够快速回滚!日常的变更操作,只要有备份,大多数情况都可以进行回滚。那些无法进行回滚的,一般都是重大变更,这时候,等着你的基本上就是直接在线上调试并修 bug 以及超长的停机时间和大批的脏数据了。


不同公司对待回滚的态度不同,和其背后的专业能力有很大关系,因此不能盲从。如果对所有的回滚事件不加甄别的进行追责,那么导致的后果就是对于非核心故障,研发坚决不进行回滚操作导致带伤上阵,或者说将回滚美其名曰快速迭代。

功能开关

比回滚更高效的方案是功能开关,在发现新功能上线有问题后,可以通过功能开关立即关闭该功能,从而起到更快速的止损效果。可以想象一个场景,一次上线后,发现 10 个功能里面有 1 个功能异常,且引发了部分脏数据,因为还需要确保其余 9 个功能正常,因此不能全并发回滚,只能按照预置的并发度进行回滚,那么回滚耗时就会较长,这时候,如果有功能开关,那情况就大不一样了。

线下测试

既然线上有了变更保障能力,那为啥还要在线下费劲搞集成测试呢,直接在线上测不就行了吗?我们假设这个观点是正确的,那么所有未经测试的代码全部推送到线上开始灰度,在灰度阶段去发现各种问题,然后回滚,修复后继续上线。但灰度的流量,也是真实的用户,怎么能够拿用户的真实流量做这样的事情呢。因此,线下测试还是非常重要的环节,通过线下测试,将 80%以上的基本问题拦截在线下环节,在灰度环节,更多的去解决线下环境无法覆盖的场景。同时,参照 Chaos Monkey,以随机的方式对线下环境以及灰度环境进行破坏性验证,让服务具备应对各种典型故障场景的容错能力。

效果检查

服务变更后,需要有一系列的基于部署清单管理的效果检查的内容,例如前面提到的程序是否正常启动,功能是否正常,性能是否正常,以及本次调整的内容是否符合预期,通过对变更的效果进行验证,才能最终确认本次变更是否正确。同时,针对服务相关的全局核心指标的监控,在变更期间,既不应该出现异常,更不能被随意屏蔽掉。

时间窗口

早期,Facebook 的交付工程团队,会在每个工作日进行一次非关键性更新,而重大更新则每周进行一次,通常在周二下午进行。这里就体现了时间窗口的概念,时间窗口主要是用来降低变更导致的影响,常见的时间窗口有如下建议:


  • 尽量避免节前做变更,即使是 BAT 和运营商,对于全年重要的节假日,往往会提前数周停止业务的非必要性变更,或者是将自动流程转为审批流程;

  • 尽量避免在业务每天的高峰期做变更,例如很多网络切割都是选择凌晨进行操作,就是避免对业务产生影响;

  • 尽量避免在下班前尤其是周五下班前做变更,提前通告并全员值守的除外;

  • 尽量避免在非工作时间(包括周末和节假日)进行自动部署。

隔离

如果服务是分组部署(多 AZ 部署、多 Region 部署),且分组间能够做到尽量避免服务间的交互和基础设施共享,那么在变更中,就需要利用该特性,对分组进行逐一升级和观察,避免问题发生扩散,在出现问题的时候,通过流量调度即可快速摘掉流量止损。

通告

任何的变更,都需要事前进行通告,告知相关的上下游团队,变更时间,变更内容,可能的影响,应急联系人等,并在变更期间的各个阶段,进行通告。同时,也应该将变更信息录入到统一的系统中,便于相关上下游订阅。这里需要注意的是,在通告系统中,各个业务方的联系方式应该基于邮件组等群组方式,避免直接写入具体的人员列表,从而因人员调整导致通告失效。

避免手工操作

对于低频非标准化的场景,在部署清单中可能会这样描述:”请将存放在 XX 地方的操作系统镜像文件集,拷贝到线上某一批服务器的 XX 路径下“。那为什么这种常规的文件替换不通过部署系统进行呢,是因为操作系统镜像文件体积太大,无法存放在版本库当中,且主流操作系统镜像每年变更至多两次,因此,大家都觉得手工操作一下就好了。但这里面存在一些高风险的地方:


  • 不对网络传输进行限速,可能会在短时间内导致服务器 IO 和网卡使用率较高,进而影响线上的业务;

  • 如果是替换操作,且直接对线上文件进行替换,因为文件体积较大,会导致在替换期间,用户获取到不完整的文件;

  • 文件传输完毕后,所有服务器上的文件是否完整,是否正确,没有校验方案。


从上述的简单 case 可知,即使简单如文件传输这样的操作,如果没有运维系统的支持而手工进行,也可能导致较为严重的线上故障。同时,也不建议为这类场景编写一次性的脚本,因为这类脚本本质上和手工操作并无区别,上述的风险并不会因为你临时写一个脚本而消失,还是应该回归正途,通过部署系统、传输系统或者其他的运维自动化平台来解决。

服务变更的最佳实践

蓝绿部署

本文以蓝绿部署为基础,介绍服务变更的最佳实践。



截图简要说明:将系统按照 AZ 的维度,独立部署了 4 组,分别是 AZ1、AZ2、Z3 和 AZ4,这四组完全一致,基于隔离的思路,四个分组间,尽量避免了服务间的交互和基础设施共享。


考虑到线上环境的复杂度,以及天然存在一定的冗余度,因此每次仅升级一个 AZ 分组。在第一个分组 AZ1 的时候,会进行较为详细的验证,除去常规的自动化检查外,还会有测试人员的手工效果检查,以此确保变更的质量。其余 AZ 因为变更内容一致,因此不会有测试人员的接入,仅保留自动化检查。


如果变更存在问题,因选择的 AZ1 是明确小于冗余度的,因此仅需要摘除流量后,再进行回滚,部分时候,如果研发要求短暂保留现场,也可以满足其要求。


部署系统

部署系统应该将变更的关键点内嵌到部署系统中,不断完善,让其成为变更流程无法逾越的环节,从而更好的保证变更质量。一个部署系统在做好单机部署工作的同时,也应该满足如下业务侧的需求:


  • 提供部署清单功能,并具备自动化的检查能力,阶段性进展通告的能力;

  • 提供版本管理功能,常规变更(二进制代码和配置)必须全部基于版本库进行;

  • 提供快速回滚功能,能够帮助业务快速回滚到上一个稳定版本,并能够按照业务上下游编排顺序进行回滚;

  • 提供时间窗口功能,默认不能够在业务定义的黑名单时间点上线;

  • 提供备份功能,每次变更都需要将可能影响到的内容进行单机备份,便于快速回滚,默认是需要将上次的发布包进行全量备份尽量排除掉日志;

  • 提供灰度发布功能,能够定义分组间和分组内的并发度,分组变更的暂停时长等;

  • 提供效果检查功能,自动化的对业务进行预定义的各类检查并和部署动作联动,如暂停变更,继续变更以及调整灰度的比例;

  • 提供编排功能,满足多模块的联合上线。


2019-08-07 08:0840189

评论 6 条评论

发布
用户头像
线下测试的顺序要往前提一下,放在第二位会更合理一些。
2020-04-08 10:03
回复
用户头像
回滚也是变更,既然是变更,就需要遵循灰度的原则,因此,即使是服务故障后的回滚,也不能全量回滚,否则会引发雪崩,当然,如果流量摘除后,整个系统完全不接流量了,那么全量回滚可能才可以进行。
2019-11-26 10:11
回复
用户头像
还应该在增加合规性检查
2019-09-18 20:11
回复
用户头像
参考文章:来自 Google 的高可用架构理念与实践
2019-09-04 11:56
回复
用户头像
参考文章:
来自 Netflix 的系统高可用建议 :https://www.infoq.cn/article/tips-for-high-availability
2019-09-04 11:48
回复
用户头像
顶大牛!
2019-08-08 10:58
回复
没有更多了
发现更多内容

浅析低代码开发的典型应用构建场景

力软低代码开发平台

编程中最难的就是命名?这几招教你快速上手

阿里巴巴云原生

阿里云 编程 云原生

九层天塔DApp合约系统开发搭建

薇電13242772558

NFT

构建数据中台——数据只有被使用起来,才能创造价值

引迈信息

数据库 数据中台 低代码 JNPF 数字化、操作系统、中台

Apple 的 plist 编辑器入门指南:基础操作与高级功能详解

雪奈椰子

文本搜索工具ack与grep

坚果

Linux 三周年连更

世优科技AI数字人产品“世优BOTA”发布!全面提升AI虚拟员工能力

联营汇聚

一个能在Linux下使用C++编写的访问RabbitMQ接收发送数据的可编译代码

linux大本营

RabbitMQ 消息队列 C++

发送GET请求时,浏览器请求的参数是指什么

linux大本营

HTTP url GET

logrotate怎么使用

linux大本营

Linux 日志管理

已知非空线性链表由list指出,链结点的构造为(data,next)。写-算法,将链表中数据域值最小的那个链结点移到链表的最前面。要求:不得额外申请新的链结点

linux大本营

链表 C语言 数据结构与算法

【源码分析】【seata】at模式分布式事务-tm实现逻辑

如果晴天

源码分析 分布式事务 seata Seata框架

nvmf协议

linux大本营

网络协议 nvme RDMA技术

再写一个版本,要求使用类进行封装,提供完善的接口,并对函数进行完善注释

linux大本营

RabbitMQ AMQP C++

写一个epoll的服务端程序

linux大本营

事件驱动 epoll C++ I/O 多路复用

为开发者搭建创新舞台 OpenHarmony创新赛正式启动

最新动态

FBEC大会 | 瑞云科技 CTO 赵志杰:元宇宙时代的基础设施——实时云渲染

3DCAT实时渲染

实时渲染 实时云渲染 实时渲染云

C语言system函数判断返回错误

linux大本营

C语言

详细讲解spdk里的examples/nvmf/nvmf/nvmf.c文件

linux大本营

nvme 文件存储

linux如何计算一个shell程序运行的时间

linux大本营

Shell Linux系统

constchar*类型的实参与char*类型的形参不兼容

linux大本营

指针 const C++

使用Plist编辑器——简单入门指南

qemu怎么用

linux大本营

qemu

终于有人把动态规划、冒泡排序、二叉树、链表、栈全部讲清楚了

收到请回复

程序员 java

Logrotate正则匹配文件名

linux大本营

正则表达式 Linux

linux如何设置一个环境变量,在shell退出之后也不会失效

linux大本营

Linux Shell export

DevOps 与研发效能资深技术专家张乐:研发效能的升维思考与降维执行

万事ONES

seq命令

linux大本营

Shell 脚本

敏捷宣言和原则

老王同学

读书笔记

PerformingTestCOMPILER_KNOWS_STDLIB-Failed

linux大本营

cmake C++

使用Plist编辑器——简单入门指南

雪奈椰子

服务变更如何做到高可用?_软件工程_焦振清_InfoQ精选文章