现代化的软件实践往往是敏捷开发、持续集成以及自动化测试等概念的组合。Bing 的开发团队最近改变了他们的开发模型,新的模型正是由这些概念所构成的,他们将这一模型称作持续交付。
在实施新思想的过程中,Bing 团队也面临了巨大的挑战,包括心理上与技术上的双重挑战。早期的团队仅包括100 名开发者,仅仅两年之后,团队就膨胀到了超过600 名开发者。伴随着团队规模的扩大,他们的自动化软件测试的数量也翻了10 倍。
InfoQ 与 Bing 团队的技术顾问 Craig Miller 进行了一次访谈,本次访谈更深入地谈论了在之前举办的一次演讲中所提到的一些内容的细节。
InfoQ:Bing 团队是通过哪些软件实现测试的管理、新代码的发布(回滚)以及部署的?
Miller:我们结合使用了开源软件(例如使用 phantomjs 进行 html 页面的测试),以及 Azure 的核心基础设施。
测试:对于每次提交,我们都要运行 2 万次测试,也就是说一天内将进行超过 2 千万次的测试执行。这个组件对于我们的持续交付系统是必不可少的,它保证代码分支可以随时进行部署,这个系统在很大程度上是不许人为干涉的。
部署过程非常简单,只是简单的文件拷贝而已(可以想象为 grep 命令),因此发布代码没什么可说的。当代码发布之后,运行时系统就会切换至新部署的代码。方法是启动新代码的进程,将来自路由器的新的连接发送给新的进程。旧的进程将在处理完现有的请求后关闭。(我们的核心基础设施基于 asp.net 和 IIS,因此代码被封装为 aspx 代码与 dll 的混合体。)
回滚的流程几乎是完全一样的,只是将发布过程反一反。方法是启动旧的代码(此时旧代码依然存在机器中),并关闭新的代码。在过去两年中,我们一共进行了大约 10 次回滚。由于我们实施的严格的测试制度和代码保护策略(例如通过测试以控制对新代码路径的访问)帮助我们减少了出错的机率,因此回滚的次数并不算多。
InfoQ:发布的过程是怎样的?听说你们一共有 6 个数据中心,你们的做法是 一次对一个数据中心进行发布吗?怎样能才“启用”新代码呢?(因为不可能通过一个可执行文件运行部署……那么正在访问 https://www.bing.com 的终端用户如何从当前版本转至新的版本呢?)
Miller:我们使用了一种金丝雀部署策略,将代码先推送至一个小的区域,随后再部署至大的区域。简单来说,我们首先将代码发布至一部分机架上的机器(大约是一个数据中心的 20%),让这部分代码先运行几分钟,直到系统确认一切正常。我们在生产环境中会进行几百种验证,如果过程中发现任何异常则立即发出警告。如果所发生的异常非常严重,则其中某些警告机制将自动中止自动化部署进程,并触发回滚机制。整个过程都是由软件所控制的。
如果第一批机架(我们将其称为伸缩单位)上的软件运行正常,我们就会开始部署同一个数据中心里另外 20% 的机器,这一过程将持续到整个数据中心 100% 部署成功为止。一旦整个数据中心部署完成,并且一切正常运行的话,我们就会在其他数据中心进行部署,这一过程基本是同时进行的,而每个数据中心仍将采用以 20% 为单元的发布策略。
用户基本上不会注意到部署的发生,因为我们对于流量的管控非常严格,保证在部署过程中不会让用户掉线。每个用户都依赖于我们的服务,所以我们从来不会让用户看到“我们正在升级服务”这种令人生畏的信息。
InfoQ:每次发布的代码量大概有多少?
Miller:这取决于这次发布与上次发布的间隔时间,以及团队的最后期限。通常来说,我们一天之内大约会进行 4 次发布,因此每隔 6 小时就会将签入的代码进行发布。我们大约有 600 名工程师在这个分支上工作并持续地进行部署,因此每次发布大约包含 100 个变更。那么如果我们某一天停止了部署工作(原因可能是某个测试失败没能够立即修复),在下一次发布时大约就会包含 400 个变更。
我们的目标是尽量让发布过程不必成为一件大事(这个目标基本上已经实现了)。一旦上一次发布顺利结束,并且平安地渡过了构建过程,系统就会自动进行部署。之所以我们以一天 4 次发布(即每 6 小时一次)作为部署节奏的上限,是出于之前提到的金丝雀部署策略的原因。
InfoQ:按照你所说,一天之内可以进行多次发布,那么怎样定义一次发布呢?
Miller:发布是指某个分支中的代码发布到所有生产环境中的服务器的过程,包括自上一次部署以来的所有变更。我们也有过在一次部署中仅包含 1 个变更的先例,因为我们认为这将使发布过程更安全。只要系统做好了准备,我们随时可以进行部署。我们对于测试与部署系统充满信心,即使需要在周末时间进行 8 次部署,大家也表现得泰然自若,也不必担心会接到紧急电话去修复某个问题。我们相信这种方式是正确的,如若不然,事情将变得令人困扰。
InfoQ:如果由于多个开发者同时在一次部署过程中提交代码,导致出现测试失败的情况,那么系统是怎样进行回滚的呢?
Miller:每个变更在进入构建系统之前必须通过测试。我们从来都不会部署未经测试的代码。如果测试失败,那么提交过程就将关闭。这一过程遵循我们部署的方式,这意味着如果我的签入有问题,那么也只有我的代码会被系统拒绝。
InfoQ:Bing 的“工作时间”是怎样定义的?
Miller:我们没有这种定义,客户同样也不会有。我们所提供的是一个全球性的服务,正如歌词中所写的“现在是五点钟”(意即总有人是醒着的),所以我们的服务是永远不下线的。
InfoQ:在测试服务器上的代码提议与部署是与其他开发者混合在一起的吗?如果这样的话,那么谁将为测试失败负责?还是说每个补丁与其他补丁是分离的吗?
Miller:在测试执行过程中,每个签入都是隔离的。所提交的代码必须在隔离情况下通过测试,如果它通过 100% 的测试(我们不允许出于任何测试失败),那么代码就可以通过,并在下一次发布时进行自动部署。
我们也将“测试服务器”与“生产服务器”的概念合二为一了,对我们来说,不存在什么测试服务器,只有生产服务器。不过,我们仅将测试的访问发送至一部分生产服务器上,并且保证没有来自客户的访问混入其中。这表示我们不会单独维护测试服务器,而是像生产服务器一样进行管理,只是将对他们的访问隔离起来。
InfoQ:很显然,持续交付概念的引入对于 Bing 团队起到了很大的积极作用。但在一开始时,人们对于这种方式能否成功持有怀疑,并且对于改变感到抗拒。那么,持续交付的思想最初是怎样引入这个团队的呢?
Miller:我本人,以及我的上司和一位同事共同启动了实现持续交付,以及让减少让客户接触到代码的障碍的概念。我们对自己与团队提出了挑战,让我们的部署系统改进一个数量级。我们清楚,实现这一目标并不容易,并且可能会在组织中引起某种不适。但我们也知道,为了最终的改进,这一切都是值得的。
现在,团队中的工程师们都开足了马力,他们能够快速地编写代码将发布给客户,这也有助于让他们感到与客户的密切联系。另一个好处是我们极大地改善了工作与生活的平衡,因此工程师们的幸福感也得到了提高,从而使他们能够为客户交付更多的价值。
InfoQ:新思想的引入是否顺利,是否曾面对某些挑战?
Miller:为了跨组织实现持续交付,有一些文化方面的障碍是我们所必须克服的。其中主要的是我们必须打破人们对于如何开发软件方面的认知障。如果你在某方面已经具有 15 年的经验,那么有许多习惯是非常难以打破的,尤其是在你能够举出某些反证的情况下。此外,能够为你所借鉴、告诉你持续交付如何取得成功的案例并不多(至少在 4 年前是这样的)。最后,规避风险是人类的本性,他们更愿意接受缓慢的改进,而不是狂风暴雨式的革命。而持续交付很大程度上就是一种革命性的过程,它将改变你开发软件、管理质量、以及将产品的点子交付给用户的方式。但毫无疑问,这一趟旅程是值得的。
InfoQ:你怎样描述现在的 Bing 团队使用持续交付的特点?
Miller:Bing 团队有许多有利条件,这能够帮助我们更好地转向持续交付的过程。
- 我们的竞争者每天都在向我们挑战,这有助于我们采用数据驱动的思想,专注于各种指标,帮助我们理解客户的真实意图。
- 我们相信工程师会做出正确的决策,并且我们的组织方式鼓励这样的决策。我们为整个组织带来了敏捷性的方面的自主权,因此每个人都将参与这一过程,并且为此负责。
- 我们团队一直以来都具备出色的创新性与探索性。一旦我们改进了编码效率,就进一步减少了创新的障碍,从而鼓励优秀的点子,让客户能够从中直接受益。
- 如果某个特性无法通过近 2 万个测试,我们是不会发布的。这也免去了对于是否要发布有问题代码的争论。如果某个测试失败,签入就会被中止,特性也不会发布。
- 来自于高级执行长官的支持对于我们是很大的鼓励,他们看到了持续交付能够为我们带来的承诺,并帮助我们在整个组织中传递这一信息。
再次感谢 Craig Miller 与 Bing 团队接受我们的采访。
关于受访者
Craig Miller是来自 Bing 部门的技术顾问,他已经为微软任职 18 年了。他热爱与工程师一同工作,打造优秀的产品与服务,让他们每天都能够服务于上百万的用户。
评论