Facebook 移动端的持续交付实践

乔梁 | 2021-12-13

持续部署是一种在软件更新准备就绪后立即将其发布到生产环境的做法,这在业界得到了越来越多的采用。由于许多主客观原因,在更新频率方面,移动端软件一直落后于云端服务。例如:

  • 手机版本只能定期发布;
  • 用户可以自行选择是否升级 App ,以及什么时间升级 App

这两点就意味着,在生产环境中同时存在多个不同的 App 版本。

另外,对于 Android 生态下,有数以百计的 Android 硬件变体,这也增加了在部署移动 App 过程中出现错误的风险。

Facebook 在提高移动端 App 的部署频率方面取得了重大进展

从 2012 年到 2016 年的 4 年时间内,Android 版本从每 8 周部署一次 提高到 每周部署一次

在本文中,我们将详细描述 Facebook 移动端 App 的部署开发部署流程。根据七年的软件工程度量数据(从 2009 年到 2016 年) 进行的广泛分析,我们发现:部署的频率并不会导致开发人员生产力的下降,也不会导致其软件质量的下降,原因在于:部署频率的提高迫使开发团队改进了其移动端 App 的发布和部署自动化,这反过来又减少了开发人员的工作量。

此外,这些软件工程数据还表明,对于持续保持 App 的发布质量来说,使用 AlphaBeta 发布策略,并从 AlphaBeta 用户那里获得质量反馈是至关重要的。

持续部署是一种软件工程实践,即一旦小批量的代码更新达到生产质量就绪后就立即将其自动化部署到生产环境中。持续部署在行业中正变得越来越普遍,并且具有许多公认的优势,包括:

  • 更小且增量式的变更使部署风险降低了;
  • 可以从最终用户那里获得更快的反馈;
  • 提高了对安全漏洞等威胁做出更快速响应的能力

部署移动 App 的关键挑战

  1. 软件更新的频率可能是有限的,因为移动平台上的软件更新对最终用户不是完全透明的,并且平台(如App Store)进行 App 审查也需要一定的时间;例如,苹果对 iOS 应用的审查。
  2. 软件 App 很难做到仅以增量方式一次仅部署其中的一个模块;相反,整个 App 都必须是一个大型二进制文件;这会增加风险。
  3. 部署风险缓解措施较为有限;例如,热修复和回滚在很大程度上是不可接受的,只有在极少数情况下才能应用,因为它们涉及软件分销商(如 Apple)的合作。
  4. 终端用户可以选择何时升级移动软件(如果有的话),这意味着不同版本的App软件需要同时在海量终端上持续正常运行。
  5. 需要同时支持多种硬件变体(尤其是 Android)和多种操作系统的变体。由于笛卡尔产品的规模:APP版本 × (操作系统类型和版本)×硬件平台,每次部署的风险都会显著增加。

鉴于上述限制,一个令人信服的悬而未决的问题是:更新和部署移动软件离“持续”有多近?

将软件开发活动与实际的发布部署活动分离

Facebook 移动关键策略是将软件开发与实际的发布和部署分离。

软件开发以很小的增量方式发生,而发布部署则是定期发生,如下图所示。

对于软件开发来说

开发人员将他们的移动软件变更推送到 main 分支,其频率与后台云端软件频率相同,并以类似规模的增量进行代码提交。只要开发人员认为他们的代码变更可以部署了,他们就会这么做。

对于发布部署来说

定期地从 main 分支上拉出一个 Release 分支。其中,Android 端在 2016 年达到每周一次,iOS 端在 2017 年也达到每周一次

Release 分支上的代码会经过更广泛的测试,对于发现的问题进行必要的修复,然后对外全网发布给用户。

Android 为例,在上图中:

Main主干

Main 是开发主干,所有代码变更都会首先提交到这个分支上。

在这个分支上,每天会产生一个 Facebook 内部员工使用的 Dogfood 版本(也叫做 Blooding Version)。

只要 Dogfood 没有阻塞问题发生,它就会作为 Alpha 版本,通过 Google Play 的测试渠道发给少量外部用户(约 10,000 个)。

Release 分支

在每周一的早上,自动从 main 分支拉出一个 Release 分支。当周的前三天,每天在该分支上发布一个 Beta 版本,会向近 300 万外部用户开放。

当在某个 Beta 版本上发现了质量问题后,开发人员需要先在 main 分支上修复并验证通过后,再以 Cherry Pick 的方式向发布工程师提出合入 Release 分支的申请。

发布工程师审核通过后,合入 Release 分支,并随着后一天 Beta 版本发布出去。

值得注意的是,在周四,该 Release 分支的状态变为“冻结状态”,即:如果不是修复那些“阻塞发布”的问题,就不再允许向该 Release 分支合入代码了。

如果Release分支上在周四和周五仍旧有代码变更,还会发布新版本,就是冻结点后的 Beta 版本。

正式发布

每周一早上( Release 分支创建一周后),Release分支上的最后一个冻结 Beta 版本会在 Play Store 逐步推出放量,即:在接下来的三天内,用户分批获得新版本的访问权限,通常先是只有 20%,然后是 50%,最后是 100%人群。每个批次发布后都会进行稳定性检查。

发布工程师团队

发布工程师团队在上述过程中扮演着非常关键角色。尽管很重要,但它的人数很少。在 2016 年时,只有不到十名成员。

之所以能保持这么小的团队规模,一是因为它拥有强大的工具和流程中较高的自动化程度,二是因为它与开发团队多年来建立起来了合作伙伴关系。

资深的产品开发人员会被借调到发布工程师团队做相关的发布工作,每两个月左右一轮换。

这种安排的第一个关键优点在于:它在发布工程师团队和开发团队之间建立起了协作伙伴关系。

开发人员接受了相关的教育,了解了发布工程师的工作内容,以及它的工作流程是什么样的,它的问题和痛点是什么等等。当该资深开发人员回到其所在的产品开发团队后,他会把在与发布工程师合作期间积累的知识传播给其他开发团队。

这种安排的第二个优点是:当该开发人员在观察到发布过程中的低效之后,在某些情况下会为发布工程师开发一些自动化工具,让发布过程进一步简化和自动化。

那么如何就能说明:在这种工作模式下,工程师的生产力没有下降,质量也没有降低呢?

敬请期待下一篇的讲解。

英文参考文献:Continuous Deployment of Mobile Software at Facebook

发表时间: November 13, 2016