《持续交付》读书笔记
其他持续交付相关文章:《持续交付》系列文章目录
第一章 软件交付的问题
1. 引言
本书的核心模式是部署流水线,以持续集成理论作为其理论基石
部署流水线有三个目标
- 让软件构建,部署,测试和发布过程对所有人可见,促进合作
- 改善反馈,能在整个过程中更早的发现和解决问题(做一件事,有问题发生是一定的,重要的是快速的定位和解决问题)
- 使在任何环境下部署和发布任意版本的应用成为自动化的过程,提高效率
一个简单的简单的部署流水线
提交阶段 ==> 自动化验收测试 ==> 自动化容量测试 ==> 手工测试 ==> 发布
2. 一些常见的反模式
2.1. 反模式:手工部署软件
这个反模式一般具有如下特征
- 有一份详尽的操作文档,其中描述了多出需要注意的地反
- 手工测试程序是否运行正确
- 总有客户来问,部署怎么又出问题了
- 如果是集群环境,个环境配置经常有出入
- 发布过程时间较长
- 发布结果无法预测(凭运气)
- 经常加班,还搞不定问题
理想的部署流程应该是
- 挑选要部署的版本和环境
- 按一下“部署”按钮
为什么需要部署自动化
- 使部署过程可重复
- 免去部署文档的维护,一个部署脚本即是所有文档
- 部署过程可审计追踪
- 摆脱对人的过分依赖
2.2. 反模式:开发完成之后才向生产环境部署
经常出现的情况
- 运维人员之前一直没有接触过应用程序
- 程序相关的配置,数据库脚本,部署文档等都没有在正式环境下测试过
- 开发团队和运维团队协作太少
导致的各种问题
- 第一次部署成了噩梦
- 开发环境和部署环境差距越大,问题越多
- 各团队之间协作焦头烂额
解决方案
将测试,部署和发布活动都纳入到开发过程中,让他们成为正常开发流程的一部分,对部署过程也进行测试
2.3. 反模式:生产环境的手工配置
这种反模式经常有如下特征
- 诶,我本地好使啊
- 集群中各节点表现不同
- 每次准备环境事件长
- 无法回滚
- 不知不觉,集群中的服务器,操作系统配置变得都不一样了
怎样解决这些问题?
采用配置管理,可以重复的创建开发应用程序所需要的每个基础设施
对于各个环境中的信息,都应该完全掌控,而且,所有环境的生成,配置的修改都应该由自动化程序实现,禁止手动修改
2.4. 如何改变这种情况
采用部署流水线,将软件的发布变成一种低风险、频繁、廉价、迅速且可预见的过程
最后的目标是实现将自动化的测试和部署,以及全面的配置管理结合在一起,实现一键式软件发布
3. 如何实现目标
为保证能持续的以高质量交付我们的软件,需要频繁的自动化发布软件
对于频繁的自动化发布软件,反馈是至关重要的,对于反馈,应该达到三个标准
- 无论什么样的修改都应该触发反馈流程
- 反馈应该尽快发出
- 交付团队必须接收反馈,并依据它做出行动响应
下面详细介绍一下这三个标准
3.1. 无论什么样的修改都应该触发反馈流程
这些修改包括对以下项的修改
- 源代码(持续集成)
- 配置信息(配置管理)
- 运行环境(基础设施和环境管理)
- 数据(数据管理)
反馈流程
完全自动化的方式尽可能的测试每一次变更
测试内容包括但不限于
- 创建可执行代码的流程必须是能奏效的。这用于验证源代码是否符合语法
- 软件的单元测试必须是成功的。这可以检查应用程序的行为是否与期望相同
- 软件应该满足一定的质量标准,比如测试覆盖率以及其他与技术相关的度量项
- 软件的功能验收测试必须是成功的。这可以检查应用是否满足业务验收条件,交付了所期望的业务价值
- 软件的非功能测试必须是成功的。这可以检查应用程序是否满足用户对性能、有效性、安全性等方面的要求
- 软件必须通过了探索性测试,并给客户以及部分用户做过演示。这些通常在一个手工测试环境上完成。此时,产品负责人可能认为软件功能还有缺失,我们自己也可能发现需要修复的缺陷,还要为其写自动化测试来避免回归测试
3.2. 反馈应该尽快发出
关键是自动化,主要通过部署流水线来实现,后面各章会详细介绍
3.3. 交付团队必须接收反馈,并依据它做出行动响应
没有响应,反馈何用?
3.4. 这个流程可以推广吗
很多思想来源于精益制造,目标是快速交付高质量的产品,聚焦于消除浪费,减少成本
这个思想已经被多个行业所证明,而且作者也经历过很多采用更持续交付的项目
4. 收效
4.1. 授权团队
让整个团队合作在一起
4.2. 较少错误
通过减少手工的重复任务,避免大部分错误
4.3. 缓解压力
让发布任务变得简单可控,免得每次发布都如临大敌
4.4. 部署的灵活性
随时找到以往的部署版本,意见部署任意版本
4.5. 多加练习,使其完美
目标是不管部署到什么环境,都使用相同的部署方法
5. 候选发布版本
每次提交代码都产生一个可发布版本
但是实际开发中,要想验证一个可发布版本,就要进行一次集成,通常这个过程难以控制,所以就会推迟,集成频率越低,越痛苦,但是越痛苦的事,越要频繁去做,要么会更痛苦
本书会通过持续集成这一实践来让集成变得无痛
6. 软件交付的原则
为了保证高质量的持续交付,下面的可以当做行为准则了
6.1. 为软件的发布创建一个可重复且可靠的过程
归根结底,软件的部署包括三件事
- 提供并管理软件所需要的运行环境,包括硬件配置,所依赖的软件,基础设施以及所需的外部服务
- 将应用程序的正确版本安装其上
- 配置应用程序,包括所需的任何数据和状态
6.2. 将几乎所有的事情自动化
能让机器去做的就别自己做了
6.3. 把所有的东西都纳入版本控制
使每个版本相关的信息都能很快找到
6.4. 提前并频繁的做让你感到痛苦的事
这是一条很有用的启发式原则
6.5. 内建质量
每个人都对质量负责,有问题立马解决
6.6. “DONE”意味着“已发布”
我们认为一个特性只有交到用户手中才算DONE,而不是开发完了就OK了
6.7. 交付过程是每个成员的责任
从相互指责扯皮到共同协作
6.8. 持续改进
戴明环(plan->do->check->act)
7. 小结
本书的目标是让发布过程变得无痛
其他持续交付相关文章:《持续交付》系列文章目录
公众号,欢迎关注
第二章 配置管理
1. 引言
定义: 配置管理是指一个过程, 通过该过程, 所有与项目相关的产物, 以及他们之间的关系, 都被唯一的定义, 存储, 检索和修改
2. 使用版本控制
2.1. 对所有内容进行版本控制
至少要将那些用于重新创建应用程序的安装文件和安装环境所必需的所有信息保存在版本控制库中,包括
- 代码
- 文档
- 工具
- 构建环境的信息
持续集成,自动化测试,一键式部署的前提都是所有与项目相关的内容都在版本控制库中
2.2. 频繁提交代码到主干
两个最佳实践
- 提交之前运行自动化测试
- 增量式引入变化,改一点提交一点
2.3. 使用意义明显的提交注释
包括下面三个部分
- 总结性描述
- 细节性描述
- 相关问题或者bug的链接
3. 依赖管理
3.1. 外部库文件管理
3.2. 组件管理
关于依赖管理更多的会在第十三章 组件和依赖管理中进行讨论
4. 软件配置管理
4.1. 配置与灵活性
就像性能调优一样,没又遇到性能问题时不要过早优化,配置也是同样道理,除非真的需要,否则没必要增加复杂性
4.2. 配置的分类
我们可以在构建,部署,测试和发布过程中任何一个阶段引入配置
不建议在构建打包时引入配置,应该保证部署之前所有的包是一样的
4.3. 应用程序的配置管理
- 获取配置信息
让所有应用程序通过一个中央服务系统(关系数据库,LDAP,Web服务等)得到他们所需的配置信息
ESCAPE工具
- 为配置项建模
一个配置项取决于三个方面
- 应用程序
- 应用程序的版本
- 运行环境(开发,测试,生产)
- 系统配置的测试
- 保证外部服务都开启
- 对与配置项相关的功能进行自动化的冒烟测试
4.4. 跨应用的配置管理
每个应用程序的配置管理都应该在项目启动时纳入一个议题
4.5. 管理配置信息的原则
- 确定注入配置的时机
- 配置项和配置值分开存储
- 总是自动化获取配置
- 每个人应该都能容易的获取当前应用当前版本在当前环境下的配置信息
- 命名简单易懂
- 确保配置信息修改的模块化,改一边不会影响另一边
- 不要重复定义配置项
- 最少化配置
- 避免过分设计
- 确保对配置操作也有测试
5. 环境管理
关键在于全自动的创建一套环境,使创建环境比修复受损环境要容易的多
为什么需要重现环境的能力
- 避免人员离职产生的知识遗失
- 修复时间往往大于重建环境的时间
- 可以保持各个环境的统一
需要考虑的环境配置信息如下
- 操作系统(版本,补丁级别和配置设置)
- 第三方包(版本,配置)
- 网络拓扑
- 所依赖的外部服务(版本,配置)
- 现有的数据及其他相关信息
为了符合我们的管理策略,评估第三方产品或服务时,应该考虑下面的问题
- 是否可以自动部署
- 是否可以对配置做版本控制
- 是否能适应我们的自动化部署策略
5.1. 环境管理工具
Puppet,CfEngine,虚拟化技术等
更多讨论在第十一章 基础设施和环境管理
5.2. 变更过程管理
严格控制生产环境,未经组织内部正式的变更管理过程,任何人不得对其进行修改
6. 小结
配置管理是一切自动化的基础
其他持续交付相关文章:《持续交付》系列文章目录
第三章 持续集成
1. 引言
持续集成的目标是让软件一直处于可工作的状态
2. 实现持续集成
2.1. 准备工作
- 版本控制
- 自动化构建
- 团队共识
2.2. 一个基本的持续集成系统
开发人员使用持续集成服务的简单流程
- 查看一下是否有构建正在运行,如果有的话,等它完事,如果它失败了,就和团队的其他人把他一起修复,然后再提交代码
- 一旦构建完成且测试完全通过,就从版本控制库中将该版本的代码更新到自己的开发环境上
- 在自己的开发机上执行构建脚本,运行测试,以确保在你机器上的所有代码都正常工作
- 如果本地构建成功,你提交代码
- 然后等待你这次提交的构建结果
- 如果失败了,停下手中的活,修复问题,转到步骤3
- 如果成功,庆祝一下,开始下个任务吧
3. 持续集成的前提条件
3.1. 频繁提交
3.2. 全面的自动话测试套件
单元测试,集成测试,验收测试
3.3. 保持较短的构建和测试过程
频繁的执行不能占据太长时间
3.4. 管理开发工作区
开发人员开始新任务的时候,应该总是从一个已知正确的状态开始
4. 使用持续集成软件
Jenkins,CruiseControl,Go,TeamCity等
5. 必不可少的实践
5.1. 构建失败之后不要提交新代码
5.2. 提交前在本地运行所有的提交测试,或者让持续集成服务器完成此事
5.3. 等提交测试通过之后再继续工作
5.4. 回家之前,构建必须处于成功状态
如果你不想第二天被同事骂的话
5.5. 时刻准备着回滚到前一个版本
按照持续继承的流程,前一个版本肯定是没有问题的
5.6. 在回滚之前规定一个修复时间
比如说10分钟没有修复问题,就回滚
5.7. 不要将失败的测试注释掉
要么测试错了,要么改出问题了,,要么测试可以删除了,酌情处理,而不是注释掉
5.8. 为自己的导致的问题负责
5.9. 测试驱动开发
6. 推荐的实践
我们任务下面的实践也是有用的
- 若违背架构原则,就让构建失败
- 若测试运行变慢,就让构建失败
- 若有编译警告或者代码风格问题,就让测试失败
8. 小结
持续集成是部署流水线的基石,即使只采用了持续集成,也会对开发流程带来极大的改善
其他持续交付相关文章:《持续交付》系列文章目录
个人站点 http://ronnie.wang
第六章 构建与部署的脚本化
1. 引言
要实现
- 自动构建
- 自动部署
构建和部署系统一直要保持活力,这个系统不仅要从项目开始就开发,而且一直持续到产品到上线维护阶段,细心设计和维护它,像对待项目源代码一样,并定期使用,确保我们每次想用时,都能正确运行
2. 构建工具概览
由于我使用Java,用Maven构建,所以其他相关工具略过
2.1. Make
略
2.2. Ant
略
2.3. NAnt与MSBuild
略
2.4. Maven
惯例由于配置
三个问题
- 项目结构死板
- 扩展它要写代码(mojo插件)
- 默认情况下,自动更新,可能会导致某次构建无法重现
依赖和配置惯例参见第十三章
2.5. Rake
略
2.6. Builder
略
2.7. Psake
略
3. 部署构建脚本化的原则与实践
3.1.为部署流水线的每个阶段创建脚本
刚开始可能只需要一个脚本,但是项目大了之后就要拆分,易于管理和维护
记住,部署脚本一定要放在版本控制库中
3.2. 使用恰当的技术部署应用程序
部署脚本应该能完成应用程序的安装和升级任务,在部署之前,他要能关闭当前运行的版本,而且既支持在当前数据库上升级,又能从头创建数据库
3.3. 使用同样的脚本向所有环境部署
将部署脚本和需要用到的配置信息分离开来,详情可参见第二章
3.4. 使用操作系统自带的包管理工具
让自己的应用程序包的安装也想apache的安装一样
3.5. 确保部署流程是幂等的
确保每次部署都以已知状态良好的环境作为起点
很难实现,作为目标前进吧
3.6. 部署系统的增量式演进
逐步完善,每自动化一个过程,就是一个进步
4. 面向JVM的应用程序的项目结构
推荐使用Maven,Maven最大的贡献就是标准化了项目结构
- 任何生成的配置或元数据都应放在target下
- 单元测试与源代码对应
- 版本控制库应该忽略target目录
- 确保应用程序所有依赖都与应用程序的二进制包一起打包
5. 部署脚本化
核心原则:对测试和生产环境的修改只能由自动化过程执行
5.1. 多层的部署和测试
- 第一层(最底层),硬件
- 第二层,操作系统,操作系统配置
- 第三层,中间件,中间件配置
- 第四层,应用/服务/组件,应用配置
保证下一层是准确的,可控的,稳定的配置,再开始上一层的部署
5.2. 测试环境配置
简单的冒烟测试,证明我们的配置可以工作,可以从如下几方面入手
- 确认能从数据库拿到一条记录
- 确认能连上网站
- 断言消息代理中的已注册的消息集合是正确的
- 透过防火墙发送几次“ping”命令,证明线路是通的,且各服务器之间提供了一个循环分配负荷
关于基础设施管理,第十一章有更详细的描述
6. 小贴士
6.1. 总是使用相对路径
如果不可避免要使用绝对路径,尽可能将这部分内容独立出来,不要让它影响构建系统的其他部分
6.2. 消除手工步骤
枯燥,极易出错,文档容易过时
当做第二次时要警觉,当你需要重复做第三次时,就把它自动化
6.3. 从二进制包到版本控制库的内建可追溯性
保证知道哪个二进制包是哪个版本库的哪个版本生成的
6.4. 不要把二进制包作为构建的一部分放到版本控制库中
6.5. “test”不应该让构建失败
不要一碰到错误就失败,最好都执行一遍流程,报告出所有错误,再失败
6.6. 用集成冒烟测试来限制应用程序
部署前简要测试一下机器是否正确,环境是否正确等
6.7. .NET小贴士
略
7. 小结
以迭代的方式来识别最令你痛苦的步骤,并将其自动化,沿着部署流水线,逐步完善自动化构建和部署能力。请时刻牢记最终目标,即在开发、测试和生产环境中共享同一种部署机制,但不要过早地纠结于工具的创建
其他持续交付相关文章:《持续交付》系列文章目录
个人站点 http://ronnie.wang
第七章 提交阶段
1. 引言
提交阶段的目标
目标主要有两个
- 要么产生成功的可部署文件
- 要么快速反馈失败的原因,并阻止部署流水线之后的进程,这样可以保证错误不向后续步骤蔓延
提交阶段的开始和结束
当向版本库中进行一次提交时,提交阶段就开始了,提交阶段是部署流水线的开始
提交阶段的结果有两个
- 成功,产生可供后续测试和发布的二进制产物和可部署程序集
- 失败,得到失败报告
2. 提交阶段的原则和实践
为了建立高效的提交阶段,需要遵循下列原则和实践
2.1. 提供快速有用的反馈
如果有问题,尽早发现,尽早修改,这样解决错误所需的精力最少
2.2. 何时让构建成功
理论上将,提交阶段的失败来自于下面三种情况
- 编译错误
- 测试未通过
- 环境配置问题
但如果通过了,是真的通过了吗,是否可能有如下情况呢
- 编译警告很多
- 测试没有全部运行
- 代码质量并不高
这样还要让构建成功吗,这需要团队讨论,建立大家认可的标准,比如规定测试覆盖率,检测代码质量,控制编译警告数量等
但首要原则是,如果构建失败,交付团队要立即停止手上的工作,把问题修复
2.3. 精心对待提交阶段
对待提交阶段用到的脚本也要向对待程序的其他部分一样精心的设计和维护
这里有一些原则可供参考
- 将脚本做成模块化的
- 将那些经常使用但很少变化的与经常要修改的任务分离开来
- 将部署不同阶段用到的脚本写到不同的文件中
- 不要写出与具体环境相关的部署脚本,将具体换进配置和构建脚本分离
2.4. 让开发人员也拥有所有权
不要只让构建专家来管理构建过程,开发团队和运维团队都应参与进来,构建专家应该专注于下面的工作
- 构建过程的设计
- 构建知识的传授
2.5. 在超大项目团队中制定一个构建负责人
主要用于维护和巩固构建纪律
3. 提交阶段的结果
制品库
保存提交阶段输出结果的地方
一个候选发布版本在部署流水线中成功走向生产环境的步骤
- 交付团队的某个人提交了一次更改
- 持续集成服务器运行提交阶段
- 成功结束后,二进制包,所有报告和元数据都被保存到
制品库中 - 持续集成服务器从
制品库中获取提交阶段生产的二进制包,并将其部署到一个类生产测试环境中 - 持续集成服务器使用提交阶段生成的二进制包执行验收测试
- 成功完成后,该候选发布版本被标记为“已成功通过验收测试”
- 测试人员拿到已通过验收测试的所有构建的列表,并通过单击一个按钮将其部署到手工测试环境中
- 测试人员执行手工测试
- 一旦手工测试也通过了,测试人员会更新这个候选发布版本的状态,指示它已经通过手工测试了
- 持续集成服务器从
制品库中拿到通过验收测试的最新候选版本,将其部署到生成测试环境 - 对这个候选发布版本进行容量测试
- 如果成功了,将这个候选版本的状态更新为“已通过容量测试”
- 如果部署流水线中还有后续阶段的话,一直重复这种模式
- 一旦这个候选发布版本通过了所有相关阶段,把它标记为“可以发布”,并且任何被授权的人都能将其发布,通常是由质量保证人员和运维人员共同批准
- 一旦发布以后,将其标记为“已发布”
4. 提交测试阶段套件的原则与实践
关于单元测试的内容,可参考另一篇文章
4.1. 避免用户界面
放到验收测试阶段处理
4.2. 使用依赖注入
4.3. 避免使用数据库
4.4. 在单元测试中避免异步
一个测试运行到异步点时,切分出来另一个测试
4.5. 使用测试替身
mock和stub
4.6. 最少化测试中的状态
持续关注“如何降低要构造测试环境的复杂性”是合理的
4.7. 时间的伪装
对于用到依赖系统时间的测试,改用stub
4.8. 蛮力
在测试套件运行过慢时,可以采用下面两个办法
- 拆分成多个测试套件,并行执行
- 将运行时间较长且不经常失败的测试放到验收测试阶段运行
这样可能导致的问题是知道问题的及时性有所降低
5. 小结
快速发现问题,快速做出反馈,快速解决问题,快快快
提交阶段虽然是部署流水线的起点,但是如果在你的流程中引入,仍然可以提供巨大的价值
《持续交付》这本书可以说使我对软件开发流程产生了新的认识,充分的意识到了当前作坊式的软件开发是多么的不堪,很多时间都被浪费掉了,下面是我的这本书的过程中记录的一些笔记
有些连接还无法点击,因为还没有全部读完
个人站点 http://ronnie.wang
基础篇
部署流水线
- 《部署流水线解析》todo
- 《构建与部署脚本化》
- 《提交阶段》
- 《自动化验收测试》todo
- 《非功能需求的测试》todo
- 《应用程序的部署与发布》todo
交付生态圈
- 《基础设施和环境管理》todo
- 《数据管理》todo
- 《组件和依赖管理》todo
- 《版本控制进阶》todo
- 《持续交付管理》todo