当前位置: 首页 > 科技观察

FeatureFlag功能发布控制

时间:2023-03-13 03:12:33 科技观察

背景在新功能发布前,产品可能会采用小流量测试的方式,或者在方案确定前使用A/B测试进行衡量。一般开发者会配合运维同学,通过一些已有的平台进行换机或者流量。本文介绍另一种便捷方式,讲解其在持续集成中的应用,并提供已有的开发框架,方便快速使用。FeatureFlagVSFeatureBranchesFeatureFlag(也称为FeatureToggle、Flip等)是一种允许控制在线功能打开或关闭的方式,通常由配置文件控制。说到FeatureFlag,一般都是和FeatureBranches比较。这两者有什么联系和区别?可以用一个简单的例子来类比:假设产品需要增加一个功能,如果你在主干上开发,那么通常的做法是前端开发人员在界面上增加功能,然后可能还有其他同学完成后端服务、安全、最终测试和错误修复并上线发布。如下图:上图有一个明显的问题,就是功能测试完成之前不能发布主分支,因为接口中已经提供了功能,必须完成才能发布给用户.当然,解决方法也很简单。比如我们经常使用FeatureBranches来解决。在trunk上拉一个branch,然后在branch上打开测试后再合并到trunk中,这样才不会影响trunk的持续发布。如果还有新的功能,那就拉新的分支来解决。如下图所示:但这也有问题。如果一个功能比较复杂,开发周期比较长,这段时间在主干上修改了很多次代码,在分支上开发完成后再合并到主干中,会是一件比较麻烦的工作。.您必须处理冲突并与其他开发人员交流变更点。这是很多人不愿意做的事情。于是有人提供了一个新的方案来解决这个问题。比如将开发工作分成多个小块,在每个分支上的开发和测试完成并及时合并到主干中,可以先隐藏接口功能,等到所有功能后才显示出来被开发。这样每次合并的难度就小很多;或者每次主干上的修改都及时同步到分支上,等到分支上开发完成后再合并到主干上就容易多了。但是,如果发布中存在错误怎么办?进行回滚并重新上线可能很常见。有没有什么办法既能避免分支合并的麻烦,保持主干随时快速迭代发布,又能更好地控制新功能的发布,方便小流量或快速回滚操作?答案是功能标志。功能标志允许关闭未完成的功能。您可以在主干上迭代开发。即使没有开发新功能,也不会影响发布,因为它是对用户关闭的。功能开发完成后,修改配置即可发布功能。这种操作甚至可以在网上完成。比如代码已经发布但是功能不可见。您可以修改配置,使该功能对特定用户可见(在线测试、小流量或全面发布等)。如果新功能出现问题,可以通过配置文件快速回滚,但必须重新分支上线。FeatureFlag原理示意图如下:每种方法都有自己的优缺点。选择合适的解决方案,不要拘泥于方法本身。没有通用的解决方案。这两种方法都有自己的优点和缺点。FeatureBranch的优点:多个功能分支同时开发,不会影响主干和在线代码。在分支上开发新功能时,无需担心影响其他正在开发的功能。现有的很多持续集成系统都支持分支构建、测试、部署等。缺点MartinFowler的文章已经做了全面的解释:分支分离的时间越长,合并代码就越困难。在分支中修改函数名可能会引入大量的编译错误。这称为语义冲突(semanticconflict)。为了减少语义冲突,将进行尽可能少的重构。重构是一种不断提高代码质量的手段。如果开发过程中存在连续不断的特性分支,会阻碍代码质量的提升。一旦代码库中出现分支,就不再是真正的持续集成了。当然,你可以为每个分支创建一个对应的CI,但它只能测试当前分支的正确性。如果在一个分支中修改了一个功能,但在另一个分支中仍然按照原来的假设使用,那么在合并的时候就会引入bug,修复这些bug会花费很多时间。FeatureToggle优点:避免了分支合并代码冲突的问题,因为它是基于主干的。每次提交都在trunk中,迭代速度优势明显。新功能的全过程不断集成。缺点:未完成的功能可能会部署到线上如果配置错误,可能会开启未完成的功能。当然,界面层可以最后显影,避免过早暴露。主线担心提交代码会影响其他功能。我们可以根据自己的需要选择合适的解决方案。FeatureFlag在避免分支合并和加速迭代方面有优势。除了支持主干开发,FeatureFlag还有哪些实用的功能?下面就来介绍一下吧。FeatureFlag类型及应用一般FeatureFlags可分为两类,如下图:发布开关:发布代码时关闭未完成的功能,寿命短,立即删除稳定的功能。整个开发过程都有预定义的值业务切换:实现A/B测试,针对特定人群发布功能,尽早获取反馈,针对特定情况启用或禁用功能。比如可以设置在指定时间点开启,这样新功能会根据设置自动上线和下线,无需手动上线,在线时可以开启或关闭适合一个特殊的话题。实现快速回退释放开关的主要目的是隐藏未开发的。功能,业务交换机可以帮助我们快速满足某些需求。比如在A/B测试中,FeatureFlag可以方便的控制显示哪些特性,提高A/B测试的可维护性。我们也可以利用配置中的逻辑,针对一小部分人甚至特定区域的人发布新功能,以尽快获得功能反馈。甚至可以启用联机调试,以便调试人员只能看到新功能。而这一切只需要配置文件和简单的标记。谁在使用FeatureFlag功能?看起来很酷,但它不是新的?谁在使用它?我不愿意冒险。事实上,FeatureFlag已经在国外的互联网公司广泛使用。例如FaceBook、Google等公司采用基于主干的开发模式进行持续集成开发,FeatureFlag就是其中一项基础技术。下图展示了Facebook发展模式的转变过程。可以看到Facebook几年前就开始使用FeatureToggle,通过FeatureFlag关闭主干上未开发的功能,保证快速迭代和高频发布。国外主干开发推荐这样一种方法:主干作为开发主线,所有开发人员在完成开发后及时向主干提交代码,不允许开发人员从主干拉分支。发布时,系统拉取分支进行发布,主干上的bug修复及时同步到发布分支。开发者可以在本地使用git等工具进行版本管理。如下图所示:虽然国外基于主干的开发模式已经成为主流,但是分支开发并不是不应该使用的东西。不建议使用分支,让新的功能代码长期堆积在分支上,分支的生命周期要短。在实际应用中,我们可以根据业务场景选择使用功能分支还是使用FeatureFlag,两者可以相互结合。比如文章前面提到的例子,可以通过分支来开发细分的子功能,让分支及时合并,通过特性标志来控制功能的发布,提高工作效率。最佳实践除了主干开发,什么时候选择使用FeatureFlag?以下是使用FeatureFlag的一些典型场景:隐藏或禁用UI中的新功能隐藏或禁用应用程序中的新组件版本控制接口扩展接口以支持多个版本的组件向现有应用程序添加新功能增强功能现有应用程序中的现有功能可以可见,因为FeatureFlag本身控制的是业务功能,所以不适合功能的大范围变更。另外,在使用过程中需要注意一些问题:只在需要的地方创建开关。酒虽奢,不可贪。滥用任何技术都会出现问题。控制开关的数量。如上,开关应按需使用,及时清除。代码在开关之间保持独立。如果代码有依赖,则无法删除,最终可维护性会变差。清除释放开关并丢弃代码。当功能稳定时,释放开关应该被移除,旧代码也是如此。最后露出界面层。这套东西复杂怎么实现?下面以php和smarty模板为例进行介绍。首先,你需要一套工具来控制代码逻辑。虽然开源框架在后端代码层有支持,但还是推荐在模板层使用FeatureFlag,因为模板直接和功能挂钩,更直观,维护起来也更方便。比如我们会提供一个smarty插件,可以让你控制相应的显示:这段代码的意思是,如果命中了common模块的featureA,则显示下面的代码,否则显示另一组代码。由于显示代码是和功能相关的,所以相当于控件显示了哪些功能。当然你也可以不带featureelse只控制function的开启或关闭。另外,我们还需要一个featureA的配置对应的配置文件,如下:{"features":{"featureA":{"type":"switch","value":"on","desc":"testswitchfeatureworkornot"}}}featureA配置的值为on,开关类型为switch。也就是说,这个功能是开启的。类似于switch,可以实现多种特性类型,比如采样控制、日期控制、区域控制等,代码逻辑只需要根据值的设置来判断是true还是false。比如采样类型,value设置为0.5,那么对应的类型逻辑只需要判断随机数是否在0-0.5范围内即可。在部署时,我们只需要修改featureA的配置即可控制功能的发布。是不是很简单!开发框架对应的开源框架有哪些?几乎每种语言都有对应的实现。例如FEXFIS组提供基于php和node.js的框架。此外,还有多种语言的开源实现:语言FeatureFlag框架phpSmarty-basedFeatureFlag框架NodeJsNode-based前端解决方案YogurtFeatureFlag框架javaTogglz.NETFeatureToggleRubyRollout,DegradePythonGargoyle,NexusadminGroovyGrailsFeatureToggleSummaryofFeatureFlag和FeatureBranches各有优势,结合使用可以发挥更大的作用。根据业务场景选择合适的解决方案。FeatureFlag可以支持骨干开发,在控制功能发布方面具有独特的优势。