Azure DevOps团队如何使用功能开关实现产品快速迭代的(每三周发布上线)

原文链接:https://devblogs.microsoft.com/buckh/controlling-exposure-through-feature-flags-in-vs-team-services

作者:Buck Hodges,Azure DevOps技术总监,曾参与TFS第一个版本的TFVC代码管理模块开发工作,并引领团队完成向云以及DevOps的转型。

译者: 周文洋,LeansoftX研发总监

一直以来我经常被问到Azure DevOps团队是如何管理以及控制功能上线的问题,特别是对与一些还没有完成或者需要在特定时间点开放的功能。
本文将介绍Azure DevOps团队是如何做到每三周完成一次迭代产品上线,并如何尽早的获取用户反馈,以及完善产品的。

目标:

我们首要的目标是将应用部署与功能上线相分离,我们想*避免*代码提交部署后*不得不暴露功能给用户*的问题,实现功能开启或关闭的灵活控制。

下一步我们想达到可以以任何条件或范围控制功能的上线(从全部用户 到 特定范围用户 到 租户 到 具体用户),通过这样粒度可以对功能进行更加灵活的控制。我们可以部署一个功能然后选择需要将此功能开放给某些账户或者具体用户。

这使得我们可以尽快的获取反馈(不仅仅是用户反馈还包括应用运行情况收集)。
另外一旦功能出现问题我们需要快速响应,并可以快速的下线功能。

为了实现以上的目标,我们需要在不重新部署任何应用以及服务的前提下完成功能标记状态的变更(功能上线、下线),我们需要所有的服务根据变更自动响应以便最小化影响范围。

最后,确立了以下目标:

  1. 将 “应用部署” 与 ”功能上线“ 分离。
  2. 功能标记设置粒度控制到单个用户。
  3. 尽早的获取用户反馈。
  4. 实现功能快速下线。
  5. 在不重新部署应用的情况下实现功能上下线。

功能标记介绍以及使用:

功能标记,也被称为功能开关,可以使我们达到以上目标。
核心点:功能开关仅仅是代码中的一个if逻辑判断,如果功能标记启用则执行新版本的业务逻辑,否则执行老版本的业务逻辑。

让我们看一个实际的例子,在这个示例中我需要控制 “拉取请求回滚” 功能是否对用户可见,如下图所示:

定义功能标记:

首先我们需要定义一个“功能开关”,我们这里使用XML文件来定义,VSTS的每一个服务都独有一套对应的功能标记,以下是这个功能标记按钮对应的部分代码:

<?xml version="1.0" encoding="utf-8"?
<!--
In this group we should register TFS specific features and sets their states.
<ServicingStepGroup name="TfsFeatureAvailability"
<Steps>
<!-- Feature Availability 
<ServicingStep name="Register features" stepPerformer="FeatureAvailability" 
<StepData>
<!--specifying owner to allow implicit removal of features -->
<Features owner="TFS">
<!-- Begin TFVC/Git -->
<Feature name="SourceControl.Revert" description="Source control revert features"

当我们部署定义在功能标记里的服务时,部署引擎将会在数据库里创建功能标记。

运行时检测功能标记状态:

在代码里使用功能标记很简单,下面是使用TypeScripts创建按钮的代码。

private _addRevertButton(): void {
if (FeatureAvailability.isFeatureEnabled(Flags.SourceControlRevert)) {
this._calloutButtons.unshift(Dialogs.revertPullRequest(this.props.repositoryContext, this.props.pullRequest.pullRequestContract(), this.props.pullRequest.branchStatusContract().sourceBranchStatus, this.props.pullRequest.branchStatusContract().targetBranchStatus)
} > {
VCResources.PullRequest_Revert_Button
});
}
}

通过界面控制功能标记状态:

我们也有内部的站点提供在线的功能标记配置,如以下示例,有一个功能标记 "代码回滚" 设置为对我的个人账户开启、对另一个账号为关闭。通过这种方式可以实现根据租户需求对功能标记进行配置

关闭功能标记:

对新功能的线上监控是非常重要的,如果我们发现某个功能出现问题,我们可以使用功能标记下线功能。
即便在没有重新部署的前提下。仅仅通过一个脚本或者在线的开关就可以将应用回滚至之前的状态。

测试注意事项:

隐藏在功能标记背后的新功能被部署到环境上默认设置为关闭。当我们对某些租户或用户开启功能时,新的业务逻辑与老的业务逻辑都会被执行。我们需要同时对新的以及老的业务逻辑进行测试,以确保应用的正常运行。这也是至关重要的一步来保证功能出现问题时可以顺利的下线

阶段:

在前面提到过,我们可以通过使用功能标记来获取用户反馈,我们内部团队也可以通过它来开始试用功能来找出缺陷,与其让每一个团队自己内部去定义自己的流程,不如我们建立了一套标准化的功能发布流程通过这种方式可以在研发阶段尽快的获取用户反馈以及发现缺陷。我们定义了适用于每个团队的阶段,功能在阶段间进展的速度取决于功能的范围、反馈以及数据统计。这些阶段包含了越来越广泛的用户群体,以及多元化的观点、看法。

阶段 0 – 金丝雀

第一个阶段主要是一些VSTS团队的账户以及内部账户,一旦功能开关启用,项目经理便负责通知用户。

阶段 1 – MVPs & 某些客户

第二个阶段将包含MVPs(微软最具价值专家),以及选择报名参加试用的客户。项目经理负责邮件通知用户。

阶段 2 – 私有预览

私有预览主要是开放一些重要的新功能以及服务给我们不长联系的一些客户进行测试。
有很多收集参加 “私有预览” 客户的方式。如社区互动、博客评论等等。
同时我们也提供邀请码、电子邮件请求、体检计划等方式。团队可以在新的导航面板上直接管理或
与 “私有预览” 客户进行沟通交流。

阶段 3 – 公共预览

公共预览主要是为了收集一些重要的功能以及服务的反馈,但是还没有完全准备好提供SLA(服务等级协议),公共预览对所有的VSTS客户开放,但是在界面的主入口上会标注 "预览版",以便客户了解到此功能并不完整。当一个功能进入到公共预览阶段 将会在VSTS的产品更新版块官宣并伴随着市场性宣传。

阶段 4 – General Availability (GA)

GA表示功能或服务已经对所有用户开放并提供相应的支持(SLA,etc)

功能标记与分支策略

通过功能标记的配置使得 Master分支上可以存在*未完成的功能*而且不会对任何其他功能产生影响。但是这里需要考虑到安全问题,比如我添加了一个Rest API,要么就彻底的关闭它,要么就考虑到功能开启后带来的安全隐患。功能标记是让我们能在Master分支上工作的一个重要利器。

功能标记有助于在Master上开发

我们在测试还没有像现在一样完善的时候就已经开始在Master分支上工作了。虽然会带来一些负担(你必须对新版本以及旧版本同时进行测试),但是换来的是你可以更快的将功能发布到生产环境、持续迭代、试验新的功能,所以它带来的价值远远的高于产生的负担。而且我基本不会特意要求任何人使用功能开关,他们都会选择使用,因为他带来的好处是显而易见的。Munil Shah有一个演讲主题:"不但要在master分支上工作,而且要做好",这对与一些增长迅速的团队来说是有一点痛苦,但是相对而言,我还是非常推荐这种工作模式。

清理功能标签

注意:很快的就会积累大量的过时的功能标记,所以当功能已经发布到生产环境并且完全可见时,团队需要在适当的时间在代码里移除对应的功能标记。通常会发生在几个星期后,或者几个月后。具体取决于功能涉及的范围。

真实事件:

我们有一个目标是允许功能在某些活动下暴露,如果你想在一些活动中暴露功能,你会何时开启它?

几年前,在Connect 2013大会中,我们在主题演讲以及Demo之前开启了大量的功能标签,导致服务无法使用了。原因是由于在同一时间打开了大量的功能标签,我们有大量的新的业务逻辑与生产环境系统进行交互,导致系统崩溃。你可以从Brian’s的博客 "A Rough Patch" 了解到更多的信息。那时我们并没有定义功能发布阶段。只有一个 "公共级别" 的概念。

通过吸取上一次的经验,我们确保功能标记至少会在活动开始前在生产环境负载下运行24小时,让我们有时间做出合适的响应,具体是修复问题还是关闭功能。
当然这会出现新的功能会被提早暴露的问题,但是可以通过将新功能入口设置在一个较难发现的位置(除了那些早期已经知道的客户)

我们遵循此策略在Connect 2015大会时发布 “Marketplace” 功能,对比Connect 2013来说进展相当顺利。

总结:

Again,功能开关帮助我们做了什么?

  1. 实现 "应用部署" 与 "功能上线" 分离。
  2. 功能发布 "配置粒度" 精准控制到单个用户。
  3. 尽早的进行功能试验并获取用户反馈。
  4. 实现功能快速回滚。
  5. 在不重新部署应用的情况下实现功能上下线。
  6. 有助于让我们在Master分支上工作。
功能标记已经变成我们进行功能发布、收集反馈的一个重要组成部分,通过使用功能标记研发团队和市场人员可以按照自己的节奏做事互不影响,很难想象DevOps链条上缺少这一利器。
posted @ 2021-02-05 09:51  周文洋  阅读(148)  评论(0编辑  收藏  举报