本文是字节跳动发布工程团队的高磊讲师在2021 GOPS 全球运维大会中「字节跳动亿级DAU客户端发布最佳实践」的分享全文。
首先做一下自我介绍:我是字节跳动发布工程团队的工程师高磊。从事软件开发工作有10多年的时间,在传统软件公司还有一些创业公司都做过,最近大概6,7年时间基本专注在DevOps方向,也积累了一些自己的理解和经验。
今天我分享的主题是【字节跳动亿级DAU客户端发布最佳实践】,通过今天的分享,希望大家可以了解字节在客户端发布方面做的一些实践。本次我将从四个方面来进行分享,分别是:1.移动端发布的特点难点,2.字节移动发布体系的介绍,3.移动发布的实践总结,4.未来的展望。
我们先从移动发布特点难点开始。
发布这个概念应该属于CD(持续部署)的范畴,也就是Devops的一部分。平时我们接触的比较多的是服务端Devops,今天的分享主题看似会偏客户端一些,但大部分的内容和理念应该是相通的;本来我之前想的是,如果能到场的话,我会做一个现场的调研,看下到场的做客户端的同学比例;不过既然现在没有这个机会,我先简单介绍服务端和客户端的发布流程的区别:
其实这里的内容并不复杂,但作为我们后续内容的一个背景铺垫还是有必要讲的。
从构建打包到包出来的这个阶段,两者应该区别不大,无非底层依赖的打包工具略有差异,最本质的区别在于出包后的流程;服务端的更新流程,是把打出来的二进制包发到我们自己的服务器上,所以他的整个过程是可控的,一方面你可以随意更新新版本;另一方面呢,万一上线的版本有问题,也能做到一键回滚;但客户端是不行的,我们的包打出来以后,一般我们会把新版的包放到服务器上,如果对于正式包,我们会上传到商店来托管,但用户什么时候过来更新,我们是不知道的;如果这个版本有问题,那你也没有办法很快会退到上一个版本,你还得规规矩矩的再走一遍这个发版的流程,这个止损的成本是比较高的。
这就是两者最大的区别:客户端升级依赖终端,不完全取决于平台,这个特性也决定了两者在版本发布全周期其他方面的不同。
具体来说,首先是部署介质,这个上面提到了,一个是可控的服务器环境;另外一个是复杂变化的终端设备,操作系统有Android/iOS, Android有很多不同的厂商,比如小米,华为, vivo等等;
第二,服务端的版本概念比较弱,一般来说,我们不用版本号去定位某次服务端的发布,但客户端不同,我们的交流语言就是某某版本,版本号是客户端发布里面非常重要的一个信息;
第三个差异点是发版周期,服务端的发版一般没有明确约定,有新功能的话可以每天都更新,一天发多次都是常态;这个也符合Devops持续交付的理念; 移动端,一般准备周期比较长,目前主流的节奏可能是1到2周一个大版本,也有一些不常更新的应用甚至可以一个月才发一次版;
第四个差异点是参与人群,服务端一般情况下只要测试阶段通过,到了发布阶段基本上就是RD来主导,但客户端因为版本比较珍惜,一个是一个,所以在发版阶段设计了很长的链路,每个阶段都会配不同的角色去完成某项工作,现在字节不少团队还有QABM这个角色,就是QA里面专门负责发版管理的同学;整体分工可以说越来越精细和复杂了;
第五点是止损效率,这个之前已经提到过了,不能很快的回滚止损这个“硬伤”可以说是造成客户端和服务端发版差异主要的原因;
最后一点是多版本并行,服务端显然常态下只会保留一个最新的版本,在上线或者灰度阶段会短暂的多版本并行一段时间,但是客户端历史上累积的这些版本会永久的保留下来,不再变更;
那么说了这么多,相信大家对两者差异应该有了一个更清晰的认识,大家可能都会想,“客户端发版”真麻烦,这个是对的,而且因为麻烦,一旦发出去以后,就要承担一些可能的风险。
下面我给大家看几个典型线上事故的例子,大家可以看下这张PPT,这是我们线上曾经出现过的真实事故,有因为错误下发64位机型安装包到32位机型导致升级失败的,有为安装包配置错误下载链接导致安装失败的,还有使用不恰当物料导致应用商店拒绝上架的…真是什么事故都有。不难看出,移动场景下发布面临的风险很多,有安全的问题,有数据的问题,有测试的问题,稍有遗漏就会给公司造成很大的损失,或者是财务损失,或者是用户流失,这些都是我们在设计发布系统时要解决的问题。
那么看了以上这些事故,再结合客户端发版的特点,就会引出几个问题:
这些问题在字节是怎么解决的?接下来我将为大家介绍字节的移动发布体系,并尝试回答以上四个问题。
首先先介绍下字节的移动发布中台发展史,大致可以分为几个阶段:
第一阶段是2017年以前,因为业务发展比较快,公司级的中台发展相对滞后,更多的是业务从自身发版的需求出发,简单搭建了一些小的jenkins集群,用来串联各种打包和测试任务;那这个状态持续了一段时间后,问题就出现了,大量分散的jenkins集群维护起来很麻烦,业务需要自己去维护这样一个平台,投入太大,很多任务编排都重复建设,没有很好的共享资源,随着业务越来越多,发版问题越来越突出,所以一个中台的出现就变得迫在眉睫了;
于是我们进入了第二阶段,从2017开始,第一代发布平台1.0就出现了,我们内部叫“Rocket”,字面意思是火箭,显然它的寓意是快,这个阶段相之前有了一些进步,最大的改变是通过jenkins提供了平台级的流水线,不同的团队可以自己定制,同时也有了专门的编译团队来解决打包的环境和部署问题,情况比之前要好了很多,jenkins出了问题有人维护,有了流水线,也可以重复执行。
这个过程大概持续到2019,一些隐患又暴露出来了,首先是jenkins打包集群,受限于jenkins本身的单master架构问题,海量的jenkins任务对于构建团队而言同样苦不堪言,多的时候一天发生10多次重启机器也不罕见,另外呢,这一期的流水线也有一些问题,过度追求灵活的配置,那会的原子能力其实不能真正算原子能力,更像是一些脚本的零散组合,缺乏系统的协议约定,带来的问题就是用户的配置成本很高,因为需要关心的细节太多了,平台和平台之间的能力联动不透明,导致各工具之间比较割裂,用户配置流水线成本很高;同时在安全等方面的流程设计不合理,导致一些卡点形同虚设;所以从2019年开始,我们开始推进第二代发布系统的建设,这一期我们做了这样几个事情:
那第三块我们整体介绍一下字节在发布体系里面的一些实践和总结。
先看这组数据:我们现在大概每周会有 10 万次的构建,每周超过 700 次的灰度,每周超过千万量级的灰度实际的人群。
我也总结出了几点关于迭代的经验,大家可以参考一下:
首先是最佳实践的问题,我们整个平台的迭代史都是以一个典型业务作为的一个模板进行持续优化的,不追求一步到位,持续迭代是最好的状态;
第二是珍惜事故,事故都是很宝贵的经验,所以我们对于每次事故就尽量要做到极致,我们要做非常完善的这个 case study,也就是“5W” 原则;这个地方需要提一下,作为平台方千万不要去甩锅,业务方没有遵守规范,那可以问下自己是不是给了业务方犯错的空间了?我是不是给到足够的引导跟支持了?我能不能让他没有犯错的空间,我能不能杜绝一切犯错的可能性?
第三个是需求,因为需求是做不完的,那怎么办呢?我觉得作为平台方,心态要开放一些,我们可以做通用的需求,平台可以尽量做到闭环;但是对一些个性化的需求,不要去强求,不把所有东西都揽下;我们可以制定规则,给其他人参与的机会,一起合作共建,把生态做大。
最后一点是平台价值是需要被度量的,还是老生常谈的那句话,不能度量的不能被改进;你如果想改进,就必须可以被度量。
其次分享一下移动发布版的发展趋势,这个趋势是我们内部这几年做平台感知到的一些变化。
首先是版本发布逐步出现高频化的趋势;从之前的单月到双周,而现在主流的业务可能是一个单周的节奏在迭代,将来可能用不了多久,可能会呈现半周/天级别的演进,这个趋势还是比较明显的;
第二是安全越来越受到重视;这应该是一个常态了,上面其实讲的比较多了,这里不再赘述;
第三是精准测试场景;传统的都是基于已经写好的用例,这些用例最大的问题在于后期没有人维护;当UI只要有一点变化,测试用例就基本上不可用,必须持续的对这个用例进行更新,这样后期的维护成本是很高的。现在基于 AI 技术的精准测试,后面可能成为一种主流,我们不需要去维护大规模的case ,它会自动根据我当前的这种场景去实时生成测试场景,我们内部也在做这方面的一些尝试。
最后一点是持续灰度的理念;随着版本的日益高频这个是必然的,也就是灰度版本和正式版本的界限会越来越模糊;你不知道哪天是在灰度,明天就正式了,过两天的又进入下一个灰度。持续灰度这个理念也是我目前感知到的一个点。
从平台视角来看,还有几个点可以稍微提一下;速度、效率、安全、成本。具体的每一点大家可以参考一下,我就不再细讲。
我稍微提一下降本这一点:为什么我们有降本呢?因为我们要存储大量的包,所以对存储是有一定的要求的。
带宽这一块可能是应用场景下比较明显的一个特点,因为如果你是一款拥有亿级用户APP的话,随着迭代周期的缩短,包的更新频率越来越高,那由此产生的带宽成本的费用也是比较高。每年的花在 CD 成本上的这个钱估计可能会上亿。钱其实还是挺贵的,我们还是想办法降一下成本。具体怎么降呢?其实有很多方法的,但是不是今天的主题,所以先不一一展开了。
最后做一下总结:今天我们讲了很多的点,有流水线、安全能力还有放量。仔细去看这些点,它们其实都在追求 balance :比如说流水线,在原子能力上太大或太小都不行,要追求它的 balance;安全和业务的 ROI 的中间的取舍,我们也要做 balance;放量这一块,我们要在速度、效果、用户体验之间追求balance。
所以总结起来,整个发布平台的迭代过程,我们都在不断追求 balance 。在特定的时间段内,想要追求平台的最大业务收益,就必须在某一方面进行取舍,不能什么都想要。
在这里分享一下我们平台的未来的发展方向:
第一,我们会对发布概念做一些延展。从目前的小发布体系,逐步的把它向大发布体系去引进。那何谓大发布体系呢?除了现在正常的升级包、热修包以外,我们可能还会把配置资源或者静态资源给也纳入整个的发布体系里面来,形成面向业务统一的一个大体系。
第二,我们会持续优化放量,对放量做一些算法模型化的优化,也尝试引入更多的一些数据维度增加它的丰富性。
第三,我们会更加精细的度量,把它形成消费的闭环,而不仅仅是去搭一个数据看板,数据很好看但并没什么用;最终还是要去消费、去改进。
今天我的分享内容就全部结束了,期待将来与大家能有更多的交流,谢谢大家。