Google分布式构建软件之三:分布式执行构建步骤
注:本文英文原文在google开发者工具组的博客上[需要FQ],以下是我的翻译,欢迎转载,但请尊重作者版权,注名原文地址。
之前两篇文章分别介绍了Google 分布式软件构建系统Blaze相关的为了提供对存储在云端的源码的访问支持而定制的文件系统和构建系统是如何工作的。这篇文章在前两篇文章的基础之上介绍了一个在大规模集群上面分布式高效率执行构建步骤的系统[译者注:就是Blaze]。正如你看到的,源文件系统和构建系统的细节对于我们实现快速高效的分布式构建是非常重要的。所以在介绍构建步骤如何分布式执行的机制之前,来关注几个重点。
首先,构建系统是基于内容的,系统内部对于输入和输出是通过基于内容的摘要来标记的,而不是文件和时间戳(例如Make)。这意味者通过比较内容摘要就能知道内容是否是相同的,构建系统在根据行为图来执行构建操作时,会把这些摘要在内部记录下来。在构建过程中为大量的源代码计算内容摘要会很耗时,主要时间都花在读取文件上。通过在内容提交的时候计算并存储摘要就可以避免这个问题,之后直接通过文件扩展属性来提供给构建系统。
另外,构建系统通过读取BUILD文件来构建一张依赖关系的图,然后使用依赖关系图去构建一个 构建行为 或构建步骤的图。通过使用行为的输出作为其他行为的输入来构建这个依赖关系图。依赖关系必须是完整指定的,而且不能有动态的依赖检测。内容摘要和指定的完整依赖意味着行为可以通过函数来表示。在这个 函数模型中 ,函数的输入是内容摘要和环境(环境变量,命令行选项),函数是把输入转化成输出的工具或脚本,函数执行结果就是输出。这些函数式的构建行为是构建工作的原子单元,从输入转换到输出是对系统透明的。这意味着构建行为是不用知道语言和工具的,例如,可能是编译C++单元,编译java文件,链接成一个可执行文件,甚至是跑一个单测。
下面是一个行为图的举例。行为的输出,例如CC行为输出是search.o,成为其他行为(本例子中是LD)的输入。
第三,我们需要每个构建行为只能使用它显示声明的输入。这意味者同样的行为,使用同样的输入执行多次,结果在二进制级别是相同的。这保证了两次构建时的输入内容如果完全相同,那就不需要再去执行本次构建行为,因为构建结果不会改变。这似乎听起来是合理的,但实际上一个行为可能依赖于除了显示声明的输入文件之外的东西,例如系统头文件的内容或者是当天的时间(考虑下由C语言预处理展开的__DATE__宏,或者是每个jar文件中嵌入的时间戳)。我们让工具来执行 不受外界影响 的行为并对一些文件类型做预处理来覆盖时间戳来避免这个问题。
现在我们继续介绍如何使用这些函数式的行为来执行分布式构建
每个构建行为是自给自足的,原子的,所以是 便携的,可以带着输入发送到其他机器上执行。这对于Google很有意义,因为我们正好在数据中心有很多机器,意味着我们可以把构建行为分发到成千上万台机器上去执行。这种模型下所有的构建行为都可以分布式执行,并发度只受行为树的宽度限制。
在很多机器上分布式的执行构建行为使得构建变快,但是我们发现机器上执行的工作都是重复的,因为很多开发人员构建的代码都是相同的。构建行为自身的函数式特性--相同的输入条件下,输出也是一模一样的--意味者我们可以很容易并正确地缓存和复用构建结果。我们计算整个请求(命令行和输入)的摘要来做为缓存的键,所以不可能“疏忽”了某些东西而错误的命中缓存结果。还记得输入文件是通过内容摘要来描述的吗?这表示即使对于巨大的内容,计算缓存的键也是相对容易的。当构建行为已经准备好远程执行时,首先计算缓存的键。如果没有命中缓存,这个行为会被执行并会在结果返回给用户的时候进行缓存。当命中缓存,就直接使用缓存中的结果。为了让缓存的结果看起来是真正执行过的,我们也会把标准输入和标准错误输出也缓存起来然后进行回放。
当改动提交到代码源里,进行第一次构建时,每个改动点影响的行为会耗时久一些,因为这些行为需要重新执行,但因为构建行为是分布式并发执行的,所以这种耗时并不是很显著的。在很多情况下,例如C++中空格和注释的改动,这种不同的输入仍然产生二进制级别上相同的结果。由于构建系统是基于内容的,所以这种情况会导致后续的行为依然能够命中缓存,所以提供了另外一种避免重复构建的方法。整体来说,最后缓存命中率超过90%。这意味即使是“干净”地重新构建也是大部分利用的之前构建的结果,所以会非常快。也可以这样理解,这些代码的改动没有影响到最终发布的库和可执行文件。
分布式构建并重复利用构建行为是如此成功地加速了构建过程,以至于我们不可避免的遇到了另外的问题。一个大工程的干净的构建可能会产生几个G的输出,这些构建通常只花费了数分钟而我们每天构建上万次,这导致分布式构建产生的数据对我们的网络和本地磁盘I/O造成了相当大的压力,本系列最后一篇会介绍我们是如何解决这个问题的。
Google分布式构建软件之三:分布式执行构建步骤的更多相关文章
- Google分布式构建软件之二:构建系统如何工作
分布式软件构建第二部分:构建系统如何工作 注:本文英文原文在google开发者工具组的博客上[需要FQ],以下是我的翻译,欢迎转载,但请尊重作者版权,注名原文地址. 上篇文章中提到了在Google,所 ...
- Google分布式构建软件之四:分发构建结果
注:本文英文原文在google开发者工具组的博客上[需要FQ],以下是我的翻译,欢迎转载,但请尊重作者版权,注名原文地址. 之前的文章,介绍了Google在分布式构建软件过程中,如何把构建过程分发到许 ...
- Google分布式构建软件之一:获取源代码
本文原文在google开发者工具组的博客上[需要FQ],以下是我的翻译,欢迎转载,但尊重作者版权,注名原文地址. 在Google,所有的产品都是在主干上开发的.这样的好处:每个人都可以查看和修改代码, ...
- Dubbo+zookeeper构建高可用分布式集群(二)-集群部署
在Dubbo+zookeeper构建高可用分布式集群(一)-单机部署中我们讲了如何单机部署.但没有将如何配置微服务.下面分别介绍单机与集群微服务如何配置注册中心. Zookeeper单机配置:方式一. ...
- Spring3.0+Hibernate+Atomikos集成构建JTA的分布式事务--解决多数据源跨库事务
一.概念 分布式事务分布式事务是指事务的参与者.支持事务的服务器.资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上.简言之,同时操作多个数据库保持事务的统一,达到跨库事务的效果. JTA ...
- spring3.0+Atomikos 构建jta的分布式事务 -- NO
摘自: http://gongjiayun.iteye.com/blog/1570111 spring3.0+Atomikos 构建jta的分布式事务 spring3.0已经不再支持jtom了,不过我 ...
- spring3.0+Atomikos 构建jta的分布式事务
摘自: http://gongjiayun.iteye.com/blog/1570111 spring3.0+Atomikos 构建jta的分布式事务 spring3.0已经不再支持jtom了,不过我 ...
- 纯干货!华为软件开发云编译构建之Maven
一.Maven介绍 Maven是一个项目管理和整合的工具.Maven为开发者提供了一套完整的构建生命周期框架.开发团队基本不用花多少时间就能自动完成工程的基础构建配置,因为Maven使用了一个标准的目 ...
- jenkins执行构建并查看结果
继完成构建项目配置http://www.cnblogs.com/yajing-zh/p/5111060.html后,则要执行构建. 回到jenkins主页之后,我们看到一个新建的项目显示出来: 点击进 ...
随机推荐
- 【Android】一道Android OpenGL笔试题
一道Android OpenGL笔试题 SkySeraph May. 5th 2016 Email:skyseraph00@163.com 更多精彩请直接访问SkySeraph个人站点:www.sky ...
- 数据分析(7):pandas介绍和数据导入和导出
前言 Numpy Numpy是科学计算的基础包,对数组级的运算支持较好 pandas pandas提供了使我们能够快速便捷地处理结构化数据的大量数据结构和函数.pandas兼具Numpy高性能的数组计 ...
- 【Hibernate框架】三种继承映射
一.综述 大家都知道,hibernate作为ORM框架的一个具体实现,最大的一个优点就是是我们的开发更加的能体现出"面向对象"的思想.在面向对象开发中,类与类之间是可以相互继承的( ...
- Nginx - Linux下按天分割日志
待完善. 可参考:https://www.iteblog.com/archives/1244
- Ue4的UE_LOG
说明:本文为Wiki上的RAMA大神文章的大致翻译 游戏模式: 在游戏模式下,你需要在游戏的快捷方式后面加 -Log,才会在游戏中显示. 编辑器模式(Play In Editor): 你可以在Outp ...
- Code Complete 笔记—— 第二章 用隐喻来更充分理解软件开发
在这章里面,提到的隐喻,类同于比喻(建模)的方法的去理解软件开发. 隐喻的优点在于其可预期的效果能被所有人所理解.不必要的沟通和误解也因此大为减低,学习与教授更为快速,实际上,隐喻是对概念进行内在化和 ...
- maven构建简单的web项目
把jdk给换掉 项目修改好了以后写个页面测试一下,结果正常 下面应该添加依赖让web项目一步步丰满起来. 0-添加依赖 1-建一个servlet 2-web.xml中添加servlet声明 3-重新运 ...
- SpringMvc相关配置的作用
1. <!-- 配置 handlerAdapter--> <bean class="org.springframework.web.servlet.mvc.SimpleCo ...
- CODEVS 天梯 代码记录
所有水题均被折叠 Lv.1 青铜 1201 #include<iostream> #include<cstring> #include<algorithm> #in ...
- .net core 产品开发问题记录
背景 最近在公司的一个产品研发中,最终还是选择了以.net core 作为主要的技术方案.本文会拟记录开发过程中于以往中区别比较大,或者可能造成的坑. 程序集无法引用本地程序集 .net core 的 ...