Facebook是世界上最大的社交网站,有超过10亿用户每月至少要登录一次,他们每天要上传超过25亿内容,支持这样一个站点的运行,还要不断发布新的功能,Facebook的工程师是如何做到这一切的?目前就职于Facebook的极限编程创始人Kent Beck在近期发表的一篇与别人合著的论文里向大家详细介绍了Facebook的开发与部署流程。显而易见,Facebook的工程师们不会像传统软件行业那样使用瀑布模型进行开发,他们不断地开发新的功能,并迅速上线,让用户能够访问到这些新功能,这就是大家口中经常提到的持续部署(continuous deployment)。在他们看来,Facebook的开发永远没有到头的那一天,代码库在不停地增长着,目前已经有超过1000万行代码,其中850万是PHP代码,代码随时间呈现超线性增长的趋势。在Facebook,所有前端工程师都工作在同一个稳定的分支上,这也能加快开发速度,因为省去了繁琐的分支合并过程。在日常开发中,每个人都用git在本地进行开发,当代码就绪之后,就会将它推送到SVN上(之所以是SVN,这是出于历史原因),这样就很自然地区分开了开发中的代码和可以上线的代码。但是为了保证网站的稳定运行,并非是工程师将代码推送到SVN上,认为可以上线,代码就能发布上线的。Facebook采用了一种兼顾了速度与稳定性的做法——将每日发布与每周发布结合到一起。所有的代码变动默认是每周发布,每次发布会包含相对比较多的变更,在每周日的下午,代码会被发布工程师推送到SVN上,随后会进行大量的自动测试,其中包含很多针对正确性和性能的回归测试,这个版本会成为Facebook员工内部使用的默认版本,正式的发布通常被安排在周二下午。发布工程师会为每个工程师的历史表现打分,内部称为“Push Karma”,比如那些代码经常出问题的人,分数就会相对较低,他们的代码自然也会受到更多的“关照”。这样做的目的是控制发布的风险,而非对某人做出评判,因此这个分数是保密的。除此之外,越是大的变更,或者在Code Review时讨论越是多的代码,也是风险较高的地方,同样会受到更多的“关照”。在每周发布以外,其他工作日每天会有两次小发布,大多是些非关键性的更新,或者是些Bugfix,极端情况下会进行更多的发布,甚至是在周末进行发布。在被纳入发布之前,代码已经经过了开发者的单元测试和Code Review,在Facebook,Code Review是非常重要的事情,他们使用名为Phabricator的工具进行Code Reivew,该工具是和代码版本管理整合在一起的。在大量的自动化测试之外,每位员工在内部使用Facebook时也相当于进行了高密度的测试,每位员工都能报告自己发现的问题,写代码的人多了,代码增长的快了,相对而言,对代码进行测试的人也多了。在性能方面,Facebook使用Perflab对新老代码的性能进行对比,如果新的代码性能不理想,并且开发工程师无法及时修复,那么相关代码就会从本次发布中剔除出去,待问题修复后再进行发布。每个小的性能问题都是不容忽视的,因为小问题会很快累积起来,变成影响容量和性能的大问题,Perflab能通过图表的形式直观地展现系统的性能。像Facebook这样一个网站,每周发布自然是分阶段进行的,首先是H1,即部署到仅有内部访问的服务器上,进行最后的测试,很多公司也称其为“预发布”;随后是H2,部署到几千台服务器上,开放给一小部分用户;如果H2阶段没有发现问题,则进入H3,部署到全部服务器上。如果在这个过程中发现问题,工程师会立即进行修复,随后重新开始分阶段的部署。当然,也可以选择回滚代码,有两种回滚方式——常见的是回滚某个变更及其依赖的文件,另一种则是回滚整个二进制包。Facebook在四个不同的地理位置分布了大量的服务器,整个发布的包大约有1.5G,一般需要20分钟来完成整个分发。为了实现这一点,分发过程中分发使用了BitTorrent,分发时也会考虑到机架和集群的亲缘性。自从Twitter开源了他们的基于BitTorrent的发布方案Murder后,通过BitTorrent进行发布已然成为了业内的标配。在发布时,与变更相关的开发者必须在线,发布工程师会通过IRC机器人进行确认,如果人不在,那么他的变更会被回滚。这样保证了问题能够在上线之初就被快速发现并修复,当然,想在这么大的一个系统里及时发现一些问题有时也是很困难的,所以Facebook会结合内部工具Claspin和外部的信息源(比如Twitter)持续地监控系统的健康状态。通过Gatekeeper系统,工程师们可以方便地控制多少用户能够访问特定的新功能,筛选的条件可以是地区,也可以是年龄,在遇到问题是也能迅速关闭某个功能的入口。在Gatekeeper的帮助下,工程师们能方便地进行A/B测试,藉此迅速收集用户的真实体验,对产品做出调整。不要忘了,在Facebook,是工程师来选择自己做什么的,那么工程师们肯定是选择把东西做出来,看看用户的反应,而不是坐在会议室里和一堆人开会去猜测用户想要什么。Kent Beck在文中表示:仅有方法论和工具是远远不够的,因为它们总是会被误用。所以,拥有鼓励个人责任感的企业文化是很重要的。现在,Facebook有大约1000名开发工程师,仅有3名发布工程师,没有独立的测试工程师。每位工程师都可以看到全部的代码,并且能提交补丁,或者提交详细的问题描述。工程师们需要自己编写详尽的单元测试,他们的代码还要通过所有的回归测试,并能支持后续的各种运维工作。除了要对自己的代码负责,他们还要面对各种巨大的挑战,往往要针对多种解决方案进行大量试验。比如,当时为了解决PHP的性能问题,有3个不同的方案同时在进行开发,当某个方案的负责人发现另一个方案更好时,他们就会停下来;最后HipHop胜出了,但另两组人的精力也没白费,他们提供了重要的备份能力。在文章的最后,还提到了Facebook的新兵训练营制度,关于这一点,Facebook的早期员工王淮在他的《调教你的新工程师 – 谈新兵训练营》中做了详细的描述。关于Facebook,有很多值得深入学习和探讨的地方,比如他们的工程师文化,比如上文提到的新兵训练营。不知您在看了Kent Beck的文章之后有何感想,能否和InfoQ的读者们一同分享一下呢。
分享到:
相关推荐
目前就职于Facebook的极限编程创始人KentBeck在近期发表的一篇与别人合著的论文里向大家详细介绍了Facebook的开发与部署流程。 显而易见,Facebook的工程师们不会像传统软件行业那样使用瀑布模型进行开发,他们...
Kent Beck的经典教程 测试驱动开发
测试驱动开发 Kent Beck (Test - Driven Development By Example) 【高清 pdf + 标签】
TDD测试驱动开发(Kent Beck) 讲解代码(C#) 不同种货币计算。
大师之作,《测试驱动开发》,Test-Driven Development by Example - Kent Beck
通过示例测试驱动开发 肯特·贝克(Kent Beck)的示例驱动测试开发 money-“示例驱动开发”中的金钱示例
Smalltalk Best Practice Patterns(Kent Beck).pdf
原版 Kent Beck, Martin Flower 的极限编程书籍。即使是当今开发速度越来越快,越来越‘敏捷’,关于极限编程的理念还是值得学习的。
测试驱动开发 肯特·贝克(Kent Beck)的测试驱动开发方法
This book presents a set of patterns that organize all the informal experience successful Smalltalk programmers have learned the hard way. Understand these patterns, and you can write much more ...
时间测试驱动开发的例子 作者:Kent Beck
学习如何编写高质量代码,如何提高代码的可读性,提升编程能力
Beck introduces a new way of thinking about programming by basing his discussion on values and principles.”, by Diomidis Spinellis, author of Code Reading and Code Quality, Software Expert Kent Beck ...
通过示例tdd 尝试肯特·贝克(Kent Beck)关于测试驱动开发的书。
(Extreme Programming,XP)是一门针对业务和软件开发的规则,它的作用在于将两者的力量集中在共同的、可以达到的目标上。它是以符合客户需要的软件为目标而产生的一种方法论,XP使开发者能够更有效的响应客户的...
测试驱动开发 英文版 非常经典的一本好书。
Test-Driven_Development_By_Example_-_Kent_Beck
测试驱动的开发:通过示例(在Ruby中) 在阅读肯特·贝克(Kent Beck)的“测试驱动的开发:通过示例”(在Ruby中)的同时进行写作。 每次提交都意味着要运行测试套件。 有关每个提交消息的更多详细信息。 并在Wiki...
它由Kent Beck和Erich Gamma建立,逐渐成为源于Kent Beck的sUnit的xUnit家族中最为成功的一个。 JUnit有它自己的JUnit扩展生态圈。多数Java的开发环境都已经集成了JUnit作为单元测试的工具。 [1] JUnit是由 Erich ...
它由Kent Beck和Erich Gamma建立,逐渐成为源于Kent Beck的sUnit的xUnit家族中最为成功的一个。 JUnit有它自己的JUnit扩展生态圈。多数Java的开发环境都已经集成了JUnit作为单元测试的工具。[1] JUnit是由 Erich ...