极客时间已完结课程限时免费阅读

11 | 研发环境:Facebook怎样让开发人员不再操心环境?

11 | 研发环境:Facebook怎样让开发人员不再操心环境?-极客时间

11 | 研发环境:Facebook怎样让开发人员不再操心环境?

讲述:葛俊

时长17:58大小16.44M

你好,我是葛俊。今天,我来和你聊聊研发环境的问题,也就是如何才能让开发人员少操心环境,甚至不操心环境。从这篇文章开始,我们就一起进入工程方法模块了。
第 5 篇文章关于“持续开发”的讨论中,我与你介绍了获取开发环境是开发工作的核心步骤之一,对提高研发效能来说是非常值得优化的环节。当时,我与你提到了开发环境服务系统以及沙盒环境,解决了开发环境的准备工作。
而这里的“开发环境”只是研发环境的一部分,特指开发机器环境,包括开发机器的获取、网络配置、基本工具以及代码的获取和配置。今天,我们就来看看整体的研发环境的配置问题,从全局上切实解决开发人员因为操心环境而导致的效能低下。
在此之前,你可以先回忆下是否对以下问题似曾相识呢?
开发人员使用的电脑配置太低,运行太慢,编译一次要 10 分钟;
测试环境不够,上线时熬夜排队等环境;
工具零散,不成系统,很多步骤需要手动操作,开发思路常常因为流程不连贯而被打断;
团队成员的环境设置参差不齐,有个别开发人员环境配置得比较好,效率比较高,但没有固化下来,其他团队成员也用不上。
这些问题,实际上都可以归结为研发环境不够高效。就像低劣的空气质量和食物质量会影响我们的身体健康一样,不理想的研发环境会严重降低研发效能。
具体来说,按照开发流程,软件研发需要以下几种环境:
开发机器;
IDE;
开发过程中使用的各种工具、数据和配置;
本地环境、联调环境;
测试环境、类生产环境。
接下来,我会按照这个顺序,分别与你介绍这 5 套环境如何配置。
因为 Facebook 在环境配置上做得非常好,比如说,他们可以保证开发人员在 5 分钟之内拿到一套干净的开发机器环境。所以,我会与你着重分享 Facebook 的实践,然后根据这些实践,总结出一套提供高效研发环境的原则。同时,我也会与你介绍一些我在其他公司的落地实践,帮助你掌握与环境配置相关的内容。

如何配置高效的研发环境?

开发机器

Facebook 从不吝啬在开发机器上的投资。每个开发人员除了有一台笔记本外,还在远程数据中心有一台开发机器。数据中心的机器用于后端以及网站的开发,为方便描述,我称之为后端开发机。而笔记本有两个用处:一是用来做移动端 App 的开发;二是作为终端,连接到后端开发机做后端和网站开发。
两台机器的配置都非常强劲。后端开发机一开始是实体机器,后来为了便于管理和提高资源利用率,逐步转为了虚拟机,但不变的是配置依然强大。在 2015 年的时候,绝大部分机器配置都能达到 16 核 CPU 、144G 内存。笔记本有两种选择,一种是苹果 MacBook Pro,另一种是联想 ThinkPad,都是当时市场上顶配或者顶配下一级的配置。
开发机器的获取和释放,则是通过共享机器池以服务化自助化的方式完成的。更多细节,你可以再复习下第 5 篇文章的相关内容。

IDE

IDE,指的是集成开发环境。Facebook 持续在 IDE 上投入,以完善其功能、一致性及一体化体验。接下来,我会以后端和网站开发为例来说明。
因为代码存放并且运行在后端开发机上,所以在 2012 年以前,绝大部分开发人员都是使用 SSH 远程登录到后端开发机,在那里使用 VIM/Emacs 这类能在命令行里运行的编辑器进行开发工作。也有人尝试在笔记本上运行 GUI 的 IDE,远程挂载后端开发机上的文件系统,但总是有卡顿,效果不好。
在这种情况下,公司首先采用的办法是,尽量提高命令行编辑器的体验,把 VIM/Emacs 配置成类似 IDE 的工具,将最常见的功能,比如代码搜索、代码跳转、Debugger 等集成进去,效果还算可以。
不过,与 GUI 形式的 IDE 相比,这种命令行的工作方式还是有一些局限性,比如,和其他工具服务集成不方便,需要记忆大量快捷键,在显示形式上不够丰富导致用户体验不够好,等等。所以,Facebook 持续投入研究 GUI 形式的 IDE。
第一个成型的 GUI IDE 是一个 Web IDE,也就是在数据中心运行一些 Web IDE 服务。这些 IDE 服务连接到开发者的后端开发机上获取代码,同时提供网页界面,供开发人员用浏览器登录,进行开发工作。这种专门的 IDE 服务解决了远程文件夹挂载的卡顿问题,同时跟其他服务集成起来也很方便。
比如,它可以与 Phabricator 的代码审查功能集成在一起,在代码中用 inline 的方式显示其他人对你的代码的 comments,也就是说,在两行代码之间显示一个额外区域,用于展示 comments。类似的,它还可以方便地与代码搜索服务、代码跳转服务、Debugger 集成,甚至还可以跟 CI/CD 工具链的发布工具集成,所以非常方便。
到 2014 年的时候,Facebook 的大部分开发人员都逐渐转移到这个 Web IDE 上去了。如果你想深入了解 Web IDE,可以参考下Apache Che项目。
这个 Web IDE 已经很方便了,但基于网页的 IDE 在易用性和安全性还是有一些局限,所以 Facebook 继续加大在 GUI 形式的 IDE 方面的投入,最后使用 Electron 框架实现了一个原生的 IDE,也就是Nuclide
Nuclide 的工作原理和 Web IDE 基本一致,都是在数据中心运行 IDE 服务,IDE 的前端则运行在本地笔记本上,通过与 IDE 服务联通实现代码编辑等功能。只不过 Nuclide 的前端,是运行在开发者笔记本上的一个原生应用,而 Web IDE 的前端是运行在笔记本上的网页浏览器而已。Nuclide 的功能比 Web IDE 更强大,易用性也更好,同时因为没有浏览器的依赖,安全性也更好一些。

本地环境、联调环境

关于 Facebook 的本地环境,我已经在第 5 篇文章中介绍过了,主要就是加快本地构建,使用生产环境的数据,从而使得本地环境更加快捷、方便。
而至于联调环境,我曾在第 6 篇文章中简单提过。在代码提交到 Phabricator 上进行审查的时候,Phabricator 会调用一个沙盒系统创造出一个沙盒环境,运行正在被审查的代码。这个系统也是用机器池实现的,同时也是一个自助式服务,也就是说开发人员可以不通过 Phabricator,直接调用 API 来生成沙盒环境。
本地环境和联调环境是开发中最高频使用的环境,对持续开发很重要。接下来,我再与你分享两个我在其他公司的实施案例吧。
第一个例子是,我在 Stand 公司搭建本地环境。Stand 的业务规模小,因此并没有使用微服务,主要的服务只有单体的网站后端服务、数据库服务 MySQL、缓存服务 Redis,以及一些数据监控服务,相对来说比较简单。
我们的做法是,把这些依赖服务尽量在本地开发机器(也就是笔记本)上都运行一个实例。实在不能在本地运行的服务,要么在本地环境运行时不调用它,要么就在调用它的时候传递额外的参数,表明这个调用来自开发环境,而被调用的服务则针对这样的调用进行特殊处理,从而达到不污染线上环境的效果。
这是一个很常见的办法,简单有效。不过,它的缺点是本地环境数据跟线上环境有区别。
如果你的系统采用的是微服务,则可以采用以下 3 种常见办法。
第一种方法是,直接在自己的机器上把所有的依赖服务都跑起来。这种方法的优点是方便,但要求开发机器配置要求高。
第二种方法是,团队维护一个环境,让大家的开发环境接入。也就是,开发者自己的机器上只运行自己开发的服务,调用其他服务时就使用这个共享环境中运行的服务实例。这种方式对开发机器要求不高,但需要团队维护一个环境,并且一般来说大家需要经常更新这个环境中的服务,整个环境容易不稳定。
第三种方法是,使用服务虚拟化工具,来模拟依赖的服务,比如MountbankWireMock。你可以参考篇文章来了解 WireMock 的使用方法。
第二个例子是,我为一个云产品团队提供联调环境。这个云产品结构非常复杂,有十多个服务,至少需要 3 台服务器;不但有软件,还有数据、组网等复杂的设置,部署很困难;更严重的问题是,这个环境一旦损坏就很难修复,需要从头再来,所以开发人员自己配置基本不可能,运维人员也是忙于维护,应接不暇。
针对这个问题,我们也是使用了机器池的办法。不过,这个机器池里面的单元不再是单个机器,而是由 3 台机器组成的服务。这个服务自助化提供给开发者使用,使用之后自动回收销毁。
同时,确保机器池中有两套空闲环境。不够就补充,多了就删除,以保证获取环境时可以马上得到,同时又不会因为有太多空闲环境而造成资源浪费。
另外,每次有了新的稳定版本,运维人员都会更新脚本,并重新安装和配置系统,保证开发人员能够在稳定版本上进行联调。
这样一来,就解决了团队开发人员的环境问题,将获取环境的时间由 2~4 个小时缩短到了几分钟。

开发过程中使用的各种工具、数据和配置

除了 IDE,开发过程中还会用到其他工具,比如代码搜索、发布部署,以及日志查看工具等。这些工具的组合,可能与你平时理解的开发环境不大一样,但事实上它也是一种广义的开发环境,对开发效率影响很大。
这部分环境的优化,主要是使用工具之间的网状互联来提高效率。关于工具的网状互联,我在第 4 篇文章中有介绍。这里,我想强调 Facebook 的另一个重要实践:重视开发体验,将开发流程中常用步骤的自动化做到极致
我用一个具体的例子来说明。我们都知道,Git 的 Commit Message(代码提交描述)是提供信息的重要渠道。但它有一个局限,就是只能存储文本,而图片在描述问题时常常比文字有效得多,也就是“A picture is worth a thousand words”,翻译为中文就是我们常说的“一图胜千言”。
为解决这个问题,Facebook 采用了以下方式:
提供了一个图片存储服务,并为上传的图片提供永久 URL;
开发了一个端测的截屏工具,截屏之后自动上传到图片存储服务,而且,在上传成功之后自动把图片 URL 保存到本地笔记本的系统剪贴板中;
提供了一个内部使用的 URL 缩短工具,避免 URL 太长占用太多文字空间。
这三个工具集成起来,一个具体的使用场景是这样的:我在写 Commit Message 的时候,如果要截屏描述修改效果,就使用一个快捷键(比如 Cmd+Alt+4)激活截屏工具,随后拖动鼠标截屏,然后使用 Cmd+v 就可以直接把图片的 URL 粘贴到 Commit Message 里面了。
这个工作流非常顺畅、高效,不仅被大量用于 Commit Message 的书写中,也经常被用在聊天工具中。后来,我到了其他公司,都会先配置这样一套工具流程。

测试环境、类生产环境

在测试环境、类生产环境的管理上,Facebook 使用一个叫作TupperWare的内部系统,以 IaC 的方式进行管理。不过,Facebook 并没有开源这个系统。如果你所在公司使用的是 Docker,那可以使用 Kubernetes 实现类似的功能。
如果你们没有使用 Docker,可以试试 HashiCorp 公司的Terraform,或者使用AnsibleChef之类的配置管理工具,来产生一套干净的环境供团队成员使用,之后再销毁,既方便又不浪费资源。
这里,我再与你分享一个我在 Stand 公司使用 AWS 管理压测环境的例子。当时我们没有使用 Docker,于是,我们选择了 AWS 的 OpsWorks 框架。它是 AWS 基于 Chef-Solo 开发的一个应用程序管理解决方案,同时支持基础设施的建模和管理。
OpsWorks 这个框架的用法也是声明式的,只不过这个声明不是纯代码,而是在 AWS 的网页上配置的,使用效果和 TupperWare 差不多,就是首先定义一个压测环境需要几台机器,需要运行什么操作系统、需要什么负载均衡器、需要什么数据库等。
然后,通过 OpsWorks 上暴露的钩子,使用代码来管理应用的生命周期,从而实现系统和应用的初始化。通过这种方式,我们可以很方便地使用 OpsWorks 产生一个云主机集群用于压测,结束之后马上删除,方便而且划算。
其实,使用 Ansible 或者 Chef 也可以实现类似功能,但需要自己开发些东西,这里我就不详细讨论了。

提供高效研发环境的原则

通过以上实践可以看出,配置高效的研发环境主要包括以下几条原则:
舍得投入资源,用资源换取开发人员时间。Facebook 之所以从不吝啬在开发机器硬件上的投入,是因为人力成本更高。
对环境的获取进行服务化、自助化。这一点可以在开发机器、联调环境的获取上,得到很好的体现。同时常常使用 IaC、配置管理系统(比如 Chef)和机器池的方法来实现,同时利用弹性伸缩来节约资源。
注重环境的一体化、一致性,也就是要把团队的最佳实践固化下来。比如 Facebook 一个常见的操作是,配置文件统一处理。以 VIM 为例,将 VIM 的配置文件存放到网络共享文件夹中,开发人员只要在自己的.bashrc 文件中加上一行就可以搞定。
source /home/devtools/vimconfig

小结

今天,我首先按照开发流程,也就是开发机器、IDE、本地环境和联调环境、开发过程中使用的各种工具及配置,以及测试环境和类生产环境的顺序,与你讲述了高效研发环境的具体实践。然后,基于这些实践,总结了 3 个基本原则:一是,用资源换时间;二是,服务化、自助化环境的获取;三是,实现环境的一体化、一致性。
我认为,这些原则和实践的背后有一个重要思路,就是 Facebook 重视环境,并持续优化环境。这一点在 IDE 的演化上尤为明显,从命令行到 Web IDE 再到 Nuclide,一直在进步。另外,在去年年底,Facebook 停止了对 Nuclide 的开源项目的维护,这也意味着后面他们可能还会有对 IDE 的一轮新的优化。
以上种种做法,使得我在 Facebook 做开发的时候,对研发环境的感觉就是不用操心,需要使用的时候直接到网站上申请就可以使用;配置也方便,团队的配置都已经在那里了;同时,环境中的各种工具、流程都很顺畅,让我能够静下心来做开发、写算法,做我最能提供价值的事情。

思考题

我在“开发过程中使用的各种工具、数据和配置”这一章节中提到的截屏工具流程,你觉得价值大吗?值得引入你所在的公司吗?如果值得的话,可以怎么来实现?
感谢你的收听,欢迎你在评论区给我留言分享你的观点,也欢迎你把这篇文章分享给更多的朋友一起阅读。我们下期再见!
分享给需要的人,Ta购买本课程,你将得18
生成海报并分享

赞 4

提建议

上一篇
10 | 答疑篇:反对996并不是反对奋斗
下一篇
12 | 代码审查:哪种方式更适合我的团队?
 写留言

精选留言(19)

  • 小名叫大明
    2019-09-16
    我看到了个人认为比较重要信息: Facebook认为人力成本更高,这个意识比较重要,很多公司没这个意识,有这个意识的确是通过延长工作时长来补,加班及长期加班又降低了非工具和环境造成编码效率,恶性循环。 慢慢理解招聘时多研发自驱,兴趣等能力的重视的原因了。哈哈

    作者回复: 很高兴能启发大家一起思考!这才是最重要的 :)

    共 2 条评论
    15
  • 寒光
    2019-09-16
    想问下老师,“一图胜千言”的解决方案有没有对应的开源产品呢?现实中这个问题太烦人了,好多流程管理系统对图片不友好,word文档又太麻烦,不好管理。

    作者回复: 这个我没有找到开源的方法 :( 当时我在一个小公司是这样做的: * 图像存储是Google Drive * 截屏上传工具是Share Bucket (https://apps.apple.com/us/app/share-bucket-image-sharing/id611078158?mt=12) 它支持上传到指定的Google Drive,同时存储URL到剪贴板。

    5
  • 我来也
    2019-10-26
    我办公用的电脑,显示器,键盘,触控板都是我自己花钱买的。 公司配的比较差。

    作者回复: 我最近公司也是自配 😎

    3
  • 大磊
    2020-01-26
    Facebook的IDE没有使用那些商业的软件吗,比如jetbrains的,免费的vscode等,我感觉这些很好用啊😂

    作者回复: 代码仓太大,导致IDE太慢。比如JetBrains的系列。另外后端代码都在数据中心的服务器上,使用IDE+远程文件速度也不行。 VSCode因为不是IDE,速度很好,远程编辑文件也不错,所以现在转向vscode了。

    2
  • 技术修行者
    2019-09-22
    关于研发环境的高效性,我目前的工作中是用资源池的方式,可以在几分钟内获取一套自定义的虚机,通过加载项目维护的Docker镜像,可以在半小时内搭建一套完整的环境。 但这种方式对于小型公司来说,有没有成本来创建和维护这样一套环境?从技术人员的角度来看,这样做很有价值,从公司长期发展的角度来说,也是有必要的。但是很多公司 不是互联网公司,它们可能是很传统的软件公司,平时没有高并发之类的需求,例如政府相关的项目,这种类型的项目,很多时候在现场开发,机器都不是自己提供的。这种情况很难保证研发环境的高效。 当然,这也许只是一个借口,用来发牢骚,我们应该抓住工作中任何机会去改善和提升。 关于思考题中的截屏,这是非常有价值的一个做法,特别有时涉及到不同组沟通讨论的时候,截图是很好的证据。我们的解决方案和你说的差不多,涉及到不同的工具,处理方式不太一样。 1. 如果工具本身支持图片存储,例如ZenHub或者JIRA,我们用工具本身来存储图片。 2. 如果工具本身不支持图片存储,我们用公司提供的网盘来存储图片,在工具中引用相关的链接。
    展开

    作者回复: 写得非常好,可以看出你们团队,以及你个人,平时是比较关注研发效能,也关注研发人员技能成长的。这样的工作环境,应该很不错!

    2
  • 寒光
    2019-09-16
    截图的这个处理方法的确很赞👍

    作者回复: 是呀,我个人超级喜欢 :)

    2
  • 送普选
    2021-01-09
    葛老师,问下测试数据环境有好的方法么?比如使用docker容器初始化MySQL实例或测试数据,测试完成后容器里的数据自动随容器销毁,不会遗留问题污染数据环境,谢谢
    1
  • Phoenix
    2020-07-28
    说到痛点了,换过两家公司,都是考虑低成本,仅仅勉强提供可用的电脑配置,又以网络安全为由不准员工自己带电脑,结果就是下面的开发机器卡,慢,死机,领导天天在讲敏捷开发,高效,请问这种情况老师有什么破局之道吗?

    作者回复: 我在你的另一个问题里回答了。祝好运!

    2
  • 技术修行者
    2019-09-22
    做到研发环境的高效性,一个基本的前提就是要意识到人的价值,人比软硬件更有价值。 如果认识不到这一点,文章中说的这些内容,会很难推动。

    作者回复: 是的是的。软件研发因为灵活性和创造性,人的价值更重要了。

    共 2 条评论
    1
  • Jimmy
    2021-10-17
    我看新闻,说是facebook已经在2018年停止维护Nuclide/Atom-IDE了,转投vscode了,vscode可以利用remote插件远程登录到数据中心的开发机上开发,速度很快,目前没有发现什么卡顿的情况,感觉这个玩意很好用。
  • Bravery168
    2021-07-16
    好的研发基础支撑工具和环境对于提高研发效率,真的是非常重要。
  • 小包
    2021-04-21
    第二个例子是,我为一个云产品团队提供联调环境。这个云产品结构非常复杂,有十多个服务,至少需要 3 台服务器;不但有软件,还有数据、组网等复杂的设置,部署很困难;更严重的问题是,这个环境一旦损坏就很难修复,需要从头再来,所以开发人员自己配置基本不可能,运维人员也是忙于维护,应接不暇。 ---------------------------------- 我们的环境及遇到的问题跟这很类似,机器池如何组建能否详细说明下,非常感兴趣 如果一套环境需要3台机器,要保持两套空闲可用的环境,那么这个机器池需要多少准备多少机器呢,具体如何操作的呢?
    展开
  • Joe Black
    2020-02-15
    其实做到这样还是需要公司自己内部有个为开发服务的运维团队的,至少要有几个岗。感觉这个在大部分中小公司不现实....

    作者回复: 在中小公司,比较好的方式是不用专职人员,但是从政策和绩效方面鼓励高效的研发实践固化和推广。实际上Facebook等公司一开始也没有专门的团队。但是这些高效时间是一直受重视的。

  • oillie
    2019-10-13
    我一般都是在jira里贴图的,然后把jira链接放到commit message里

    作者回复: 这样做步骤比较多。不过也还可以 :)

  • 于小咸
    2019-09-18
    之前想在公司应用trunk base的代码管理,发现总会跟别人的代码产生冲突,但每个人负责的模块不同,按理不应该冲突才对。学到这里恍然大悟,我们的开发环境和测试环境混合在了一起,并且代码没有及时同步!由于我们是一个机器人团队,每台机器人既是开发环境也是测试环境,大家通常会在机器人上进行开发,但机器人没办法分配给每人一台。 代码分散在了不同的测试环境中,没有及时同步到仓库,而测试环境又是大家共享,当同步代码时就不可避免地产生了冲突。
    展开

    作者回复: 很高兴能给你一些解决问题的思路 :) 反正原则是想方设法让大家尽快合并代码,尽早解决冲突!

    共 2 条评论
  • 李双
    2019-09-17
    都是基于长远考虑,学习了

    作者回复: 嗯,一直都是在短期和长期之间权衡 :)

  • 刘晓光
    2019-09-16
    请教一个问题,开发机能够快速分配,有没有回收的策论?能给介绍一下么?

    作者回复: 开发机器因为是开发人员经常要用,所以应该长期运行,而且系统不应该主动回收。通常来讲,可以限制每个人有1~2台。

  • 许童童
    2019-09-16
    让开发流程顺畅,不阻塞,就等于是提高了效率,提升了研发效能,而且这种提升是每个开发者,员工能立即享受到的提升。

    作者回复: 是的。这种环境开发起来很舒服。员工满意度容易比较高。

  • Weining Cao
    2019-09-16
    我们现在遇到的一个问题是线上测试资源不够。因为我们发布的软件要支持mac系统,可是目前没有找到合适的提供mac虚拟机的服务商,可是买mac硬件又很贵。。。所以现在大部分mac环境提测的job都会长时间排队。。。

    作者回复: 美国那边有Mac IaaS服务,比如MacStadium(https://www.computerworld.com/article/3431659/macstadium-announces-cloud-based-mac-iaas-for-developers.html) 不过在国内好像没有听说过。我搜了一下也没有搜到。。。