今晚无意间进入去哪儿技术沙龙的直播间,听到他们要删除50%的代码和停掉50%的服务。我就想起Meta公司最近写的这篇博客:Automating product deprecation。
这篇博客对于效能平台的建设非常具有指导意义。文章最后有原文链接和我个人的总结。
这是一个系列博客。请关注我,我会连载这个系列。
译文:
在Meta,我们通过构建和交付许多不同的产品不断进行创新和尝试,这些产品包含了成千上万的独立功能。作为健康的技术生命周期的一部分,一些产品或功能将不可避免地被弃用。比如,我们在2015年推出了一款叫“Moments”的照片分享应用,后来在2019年停止服务。那么,我们该如何高效、安全地删除与Moments相关的所有代码和数据,而不对Meta的其他产品和服务造成不良影响?
在这个三部分组成的博客系列中,我们将讨论从复杂的产品组合中删除产品时涉及的复杂性,以及Meta为驱动这个过程而构建的框架,即我们的系统代码和资产删除框架(SCARF)。SCARF对Meta产生了重要影响。去年,它删除了存储在21个不同数据系统中1280万种不同数据类型的PB级未使用数据。在过去五年中,它删除了超过1亿行代码。
第一篇文章将介绍在大型组织安全地弃用产品时面临的复杂性,以及我们开发的内部工作流程工具。第二篇文章将解释SCARF如何自动删除死代码以及支持其的基础设施。第三篇文章将讨论SCARF的编排,以安全地识别和删除各种数据系统中的未使用数据类型。
失败模式
如果没有详细的指南来确定何时以及如何删除产品或功能,可能会出现一些失败模式。想象一下,为了某个每隔几年举办一次的大型活动而启动具体时限的功能。将所有相关的代码和数据保留到下一次大型活动是否有意义?大多数情况下,与其多年维护未使用的代码,不如在下次大型活动时重新开发。
尝试清理的工程师可能会发现这是一项非常耗时的工作。正确识别与产品相关的所有代码和数据,并仅针对这些特定的代码和数据进行删除是一个费力的过程。仍在使用的表或共享用例仍需要的代码可能会被错误地包含在删除范围内。例如,某些表可能在产品之间共享。假设在成为独立应用之前,Moments可能是作为Facebook照片功能的扩展而诞生的。
最重要的是,任何清理工作只能删除已经停用或完全未使用的内容,这一点至关重要。删除正在生产中使用的内容可能会给用户糟糕的体验。像Facebook这样大型产品中功能的高度互相关联性使这种情况成为一个非常现实的可能。
我们是如何解决这个问题的?
Meta开发了一些手册来描述如何安全地弃用产品。这些手册阐述了如何通知用户并给他们时间下载数据、如何安全地禁用产品以及何时最终删除底层代码和数据。它们描述了如何以及何时执行产品或功能的弃用,但实际上删除产品或功能的代码和数据是工程问题的工程解决方案。我们构建的工程解决方案并不是要取代这些指南,而是使工程师能够更安全、更高效地完成产品弃用流程。
在这篇文章中,我们将描述Meta的SCARF以及它如何指导工程师完成此清理过程。在后续文章中,我们将讨论它的局限性以及如何通过我们的自动死代码和数据删除平台来缓解这些局限性。首先,我们介绍Meta的内部工具套件,这些工具是为了协调这两个系统而开发的,以指导工程师删除具有复杂依赖关系的大型产品。
引入工作流程管理
为了简化删除产品的任务,Meta在SCARF中内置了产品弃用工作流管理工具,帮助工程师安全高效地删除产品的死代码和未使用数据。该工具让工程师了解并拆分他们在弃用期间将经历的步骤,并协调SCARF的操作,使自动化符合工程师的指导。
确定弃用范围
了解产品的其他组件何时使用一段代码或数据非常重要,而检测其他产品代码中何时引用资产对于安全弃用(区分内部和外部依赖)至关重要。比如,我们不想在两个不同的产品之间留下无效的网络链接,因为这可能导致糟糕的用户体验。弃用产品的工程师必须仔细考虑产品外部边界中的每一个此类依赖。
为了避免这些复杂性,工程师通过确定项目范围、递归添加应该删除的任何资产以及标记应该切断的依赖关系来启动弃用。比如,如果Moments与Facebook应用的共享功能集成,则必须断开这种依赖,因为Facebook共享功能本身可能不在删除范围内。
但是,如果共享功能是Moments独有的,那么这将改变删除的范围,因为我们也想删除该组件。随着项目的进展,将新资产添加到项目范围中需要进一步分析以发现内部和外部依赖关系的新边界。当工程师发现需要删除的额外组件时,这些依赖关系预计会随着时间的推移而变化。或者,我们可以识别实际上是共享组件且不应该删除的代码。试图从一开始就确定这个边界是非常困难的,因此我们允许开发者随着弃用的进展重新定义边界,以反映这种不断增长的理解。
在大型产品中,组件图、其内部和外部依赖以及相关数据资产可能非常复杂。SCARF简化了这个问题,只要求工程师在边界做出“标记依赖”或“添加到项目”的决定。然后,它在内部计算项目内所有内容的正确删除顺序。
创建删除路线图
一旦确定了要删除的未使用资产集合,SCARF将分析内部和外部依赖性并创建删除路线图,概述安全删除所有内容的正确步骤顺序。路线图每天都会随着变更而刷新,无论是删除目标资产还是通过“标记”和“添加”操作修改组件图。该路线图是工作流管理工具最重要的功能之一。
如果没有指导,工程师可能会尝试通过删除整个代码目录来一次性删除所有内容,而不考虑外部系统的依赖,而外部系统的依赖无法以原子方式提交。另一个例子包括在读取和写入数据的代码之前删除数据,这可能导致创建必须再次清理的新数据。弃用必须交错进行,以适应这些不同的要求,这意味着每次弃用都必须以协调的、多步骤的过程执行。
关键的实现细节是业务逻辑的编码,使产品和应用程序能够在Meta的系统中运行。通过对用户如何与产品互动以及这些产品如何与其他Meta服务通信进行编码,我们可以确保上游资产总是在其依赖项之前被删除。例如,通常一个产品将包含跨多个存储库的多种不同语言的代码。工程师需要删除他们的移动代码(Java、Objective-C),以便释放和删除他们的服务器端GraphQL定义。删除这些GraphQL定义就可以删除业务逻辑;删除业务逻辑可以删除数据模式定义,从而可以删除未使用的数据。
下图是一个假设示例,展示了在工程师的删除路线图中呈现的信息类型。
这个顺序一开始并不明显!这些系统边界之间的联系通常比同一语言中的两个类之间的联系更弱;并且该联系通常只能由工程师在对其代码变更请求进行连续测试期间发现。SCARF对这些系统间边界的编码支持删除路线图,从而使工程师能够安全地错开他们的删除操作。
为分析提供动力
SCARF的工作流管理工具由静态和动态分析相结合的详细指标提供支持。关于代码的信息是从SCARF的统一代码依赖关系图中收集的,关于数据的信息是从SCARF的数据资产使用分析中收集的。这些机制将在我们后续的博客文章中有更详细的讨论。
这些指标为工作流管理工具提供了一个非常重要的属性:如果可以找到资产的指标,则该资产正在使用中,并且应该阻止自动删除。相应地,任何没有可用指标的资产都可以自动删除。有了这些指标,SCARF就可以向工程师准确解释到底是什么阻碍了自动化,以及他们必须手动执行哪些步骤才能使自动化继续进行。
这种完整性属性允许SCARF自动开始删除未使用的代码和数据,同时向工程师展示哪些事情必须手动处理。在该过程的每一步中,工程师和自动化都会共同努力完成弃用。
一旦工程师根据这些信息采取行动并根据删除路线图删除了更多死代码和未使用数据,SCARF的持续索引和分析将检测这些更改并自动触发它可以进行的任何代码/数据清理。最后,工作流管理工具将更新其删除路线图,以识别下一组需要手动干预的项目,并重复该过程。
自动化就足够了吗?
SCARF强调的一些使用信号(例如仍在接收流量的API端点)如果被忽略,并不一定会导致编译错误,对于是否应该停止自动删除更主观。如果产品的某个端点每天收到一个请求,我们是否应该立即删除它?我们已经确定该端点属于我们要删除的产品,因此我们知道它最终应该被删除,但何时正确删除它的答案最终取决于业务决策。此外,我们知道错误是可能发生的,自动化也不会100% 完美。因此,SCARF需要谨慎行事,因为错误的删除可能导致不可恢复的错误或数据丢失。
相应地,SCARF提供了覆盖阻止自动化采取行动的信号的功能。在上面的例子中,工程师可能会决定我们希望继续删除API端点,尽管流量很小。这在清理内部产品、工具和服务时非常有价值。内部工具的构建和弃用的节奏通常比外部产品快得多,SCARF可以帮助确定每个内部用户工具,需要询问他们是否同意删除该工具。
此功能在工程师和自动化之间创建了反馈循环。我们的自动化会突出显示使用信号;然后,工程师对这些使用信号进行分类(通过修改代码来删除它们,或者如果适用,将信号标记为不足以阻止删除);那么我们的自动化就可以继续推进SCARF项目了。
为了进一步加快工程师手动更改的速度,SCARF还提供了即时代码更改功能。SCARF提出了一种通过有针对性的代码更改来断开依赖关系的方法,工程师可以从一组预定义的可选方法中选择一个来断开依赖。更改可以立即预览,并可以立即生成更改请求以供其他工程师审核。
在工程师完成大部分删除路线图并删除入口点、客户端代码、服务器代码和范围内的任何其他资产后,他们将留下未使用的数据表,这些数据表现在可以由SCARF自动清理。我们将在未来的博客文章中更详细地解释这种自动化。
与 Meta 上的其他工具集成
SCARF的用途不仅仅是产品弃用。当通知工程师关于单个资产的日常维护或升级工作时,我们会提供弃用作为一个选项。例如,当要求开发者迁移旧的内部API时,我们可以为他们提供一个选项,将调用方或受影响的产品弃用并导入SCARF。在许多情况下,弃用某些东西可能比执行简单的升级需要更多工作,但弃用意味着将来不需要进行维护。一旦移除某些内容,未来的维护成本就会为零。
译完
原文链接:https://engineering.fb.com/2023/10/17/data-infrastructure/automating-product-deprecation-meta/
我的总结:
1. 弃用产品是降本增效的一种手段。
2. 如何以及何时执行弃用,是一个产品运营问题。
3. 如何让工程师能够更安全、更高效地完成产品弃用流程是一个工程问题。SCARF框架就是为了解决此问题。其实放在国内,可能是效能平台的一个功能。
4. 工程师在弃用产品的过程中可能会出现的问题:
1. 工程师无法轻松地确定弃用的范围;
2. 弃用的步骤可能取决于业务代码的逻辑,也就是弃用步骤是视情况而定的。
5. 弃用产品的内容包括:代码、数据。
6. 这个框架的内容如下:
1. 打弃用标记:工程师可以通过工具,或者在平台上对要进行删除的资产(代码、文档等等)和要断开的依赖关系进行标记;
2. 分析依赖关系以确定弃用范围:SCARF通过分析依赖关系,确认弃用范围;
3. 输出弃用路线图:SCARF将分析内部和外部依赖性并自动创建删除路线图,概述安全删除所有内容的正确步骤顺序。其中可能有些步骤必须手动执行。路线图不是静态的,它会随外部条件变化而变化。
4. 在工程师删除代码后,未使用的数据表,可以由SCARF自动清理。
下一篇将介绍如何自动删除无用代码。请记得关注我。