写点什么

互联网行业持续交付的经验

  • 2012-12-19
  • 本文字数:3544 字

    阅读完需:约 12 分钟

持续交付概念的流行反映了业务部门对于更快交付速度的渴望和技术团队对交付这一老大难问题的重视。从持续集成到持续交付,ThoughtWorks 一直在积极的实践、思考、总结。这篇文章中我将分享 ThoughtWorks 一支开发团队在这个领域的收获和总结。

背景

我们的客户是澳洲的房地产搜索门户,每年独立访问者近 300 万 (澳洲人口 2000 万),年营收近 3 亿美金,澳洲 61%的房产都在此网站展示。我们的团队工作在商业地产、住宅、土地购置等与盈利息息相关的全产品线的核心系统上。

成就

2 年前,与大多数“常规”项目一样,部署和发布是一件费时费力、加班加点的活动。作为一家历史超过 10 年的互联网公司,已经有大量复杂的业务系统支持着线上业务的正常运转,部署和发布任何一个功能都是牵一发而动全身的复杂活动。对我们的客户来说快起来不是一件容易的事情,但它不得不快,因为竞争对手在频繁的进行商业活动,不快速的求变、求新它将难以保持领先的市场地位。持续交付以及持续交付所支撑的持续创新能力是它必须建设的核心竞争力。

对于 ThoughtWorks,持续交付是增加项目进度的可见性,降低项目“最后一公里”风险的重要工具。这样,投资建设持续交付能力成了合作双方一拍即合的决定。经过了两年的摸索与实践,总接下来, 收获主要有以下四点:

一键部署:目前的部署流水线从提交开始,到自动运行各种验证,再到最终的安装、配置软件可以做到全程无须人员干预,最终的部署过程可以在几分钟内自动完成。具备了快速部署,持续部署的能力,一天多次部署,一周多次发布就成了顺利成章的事情。

由离岸团队执行部署和发布:中国团队的成员大多是开发人员,对产品环境了解不足;分布式环境让中国的团队没有太多的机会从澳洲团队身上学习如何部署和发布,这样的内忧外困下,得出“由离岸团队来执行部署和发布风险太高”这个结论似乎是很自然的,然而随着持续部署过程越来越熟练和成熟,我们发现上面的结论是与部署手段原始落后的现状息息相关的,一旦发布手段变的高明,由离岸团队部署和发布的风险是完全可以接受的。

业务人员变得更加敏捷:随着部署肌肉的越来越发达,业务人员开始习惯了这样一种对话方式,“唔,这个功能很不错,我们发布出去看看用户是什么反映吧?”,和以往仔细计划、严格执行的风格相比,业务人员的决策过程变成了:

  1. 尝试某功能
  2. 通过对响应数据的分析,理解功能的市场反应
  3. 决定继续开发还是改变方向,不断循环和迭代

通过功能频繁上线,业务人员的思路和做事风格也变的更加敏捷。

业务团队与技术团队理解了部署和发布软件是两个不同概念、两件独立的活动:2 年前,项目部署和发布的时间点从来都是高度统一的,部署结束发布就结束。团队一直没有意识到软件的部署和发布是不同的概念和活动。事实上软件部署是技术概念,包括了:

  • 创建和管理应用所依赖的硬件软件环境
  • 把正确的软件安装到上述环境中
  • 正确的配置产品,使其按照预想的方式运行

软件发布则是业务概念,它包括了决定:

  • 哪些业务功能应该让用户使用?
  • 在什么时间让用户使用?
  • 让哪些用户使用?
  • 必要的市场推广,客户、支持团队培训是否就绪?

通过技术改造,大家明确了部署是一周进行多次,甚至一天进行多次的技术活动,而发布则严格与业务目标对齐,通常以几周为频率。

最佳实践

团队所取得的成就来自于对方法、工具和流程的摸索和应用,我们认为有三个实践对于实施持续交付是至关重要的:

功能开关 (Feature Toggle):持续交付不仅仅意味着使用新工具、新方法。它还意味着从设计和编码阶段就需要作出改变,功能开关是其中一项重要的设计实践,它的目的是方便的打开和关闭某个特性。为什么需要功能开关? 因为在持续交付的过程中,团队会遇到下面的情况:

  • 功能没有就绪,还不能让用户使用
  • 功能就绪,但是相关的业务活动(培训,市场活动等)没有就绪,不能让用户使用
  • 业务人员要求功能只开放给部分用户
  • 测试不充分导致的产品缺陷需要关闭功能

功能开关可以用于解决上述问题。它的具体实现多种多样,我们在不同的场景中使用过:

  • 灰度上线:功能部署上线但是把用户可见的操作都屏蔽掉
  • 文件配置:通过配置文件决定某个功能是否对用户可见或关闭
  • 状态数据:通过数据库中的状态值决定某个功能是否对特定用户可见或关闭
  • 编译参数:再编译过程中通过编译参数决定某些特性打开或者关闭

自动化 (Automation):要想频繁的部署、发布而且每次部署都不能出错,是难以离开自动化过程的,我们团队的自动化部署流水线是这样设计的:

  1. 本地测试通过后,开发人员提交代码。
  2. 触发 package: 执行静态检查,单元测试和功能测试,并生成编号的二进制包供后面的阶段进一步测试。
  3. 触发 acceptance_standalone:在 EC2 上搭建出单机产品环境,运行集成测试。
  4. 触发 acceptance_staging:在 EC2 上搭建出最小集群环境,运行另外一些集成测试。
  5. 触发 publish:将 package 阶段生成的二进制包发布到公司内部的软件仓库中
  6. 利用命令,测试人员可以自动化地取出第二步所生成的二进制包,并自动搭建出产品环境进行手工测试。
  7. 手工触发 deploy:相关发布包被安装在产品环境上,完成部署。

我们使用了很多软件来支持上面的自动化部署过程,比如 :

  • Buildr: 用于编写自动化构建脚本
  • JUnit:用于编写与运行自动化单元测试
  • Cucumber:用于编写与运行自动化验收测试
  • Amazon EC2: 用于创建和管理测试环境的虚拟服务器
  • VMware vSphere: 用于创建和管理产品环境的虚拟服务器
  • Chef:用于基础设施 (操作系统,应用服务器) 的搭建和配置
  • Go: 用于设计和实现部署流水线

虚拟化:虚拟化提供了充分测试所需的平台。能够高度自动化的测试和发布并不意味着高质量的部署和发布。在测试过程中能不能发现问题是非常关键的。不难理解,测试环境和产品环境越相近越容易发现问题,但产品环境通常复杂而昂贵,传统方式根本无法有效的向每个开发人员提供一套环境用于测试,而虚拟化则可以做到这一点。

我们目前在 EC2 上搭建出了 300 多套环境供 300 多澳洲和中国开发人对软件进行充分的测试,它的优势有:

  • 容易复制,并且可以根据需求弹性的增加。
  • 容易同步,产品环境的变化可以通过脚本自动的同步到测试环境,减少差异。
  • 容易自动化,有大量的开源软件支持

教训

当然在实施持续交付的过程中,我们也犯过很多错误、走了一些弯路,比如:

没有设计防呆机制,开过自动档汽车的人都知道,不踩下刹车无法挂前进档,这就是一种防呆机制。一个高度自动化的部署过程也需要设计防呆机制,防止出现重大错误。我们曾经因为错误的修改了脚本,高度自动化的流水线很快将测试数据刷入了产品环境,结果巴掌大一块空白出现在百万级访问量的产品首页正中间,没有防呆机制的高度自动化环境很带给团队的可能是更快的部署过程,也可能是更多的线上严重错误。

没有精确复制产品环境:我们的产品曾经通过部署流水线的验证并成功上线,然后很快客户发现产品的背景和布局出现了明显的错误。紧急排查后发现错误来自于一段排序算法,这个算法在测试环境使用的 ree-1.8.7 中没有问题,但在产品环境的 ruby-1.8.7 会出现异常。它教会我们不能想当然,产品环境和测试环境的任何一个差异点都可能是潜在的问题点。

脆弱的部署流水线带来的高维护成本:环境越接近真实,测试就越复杂脆弱,相应的维护成本也越高。自动化程度最高的团队目前有 50% - 70% 的构建失败是由环境问题引起的,比如:搜索引擎不稳定,会出现清理和更新数据失败的问题、从第三方获取的广告不稳定导致导致超时失败等。这些失败带来的直接成本是修复构建的时间,间接成本是团队需要花时间设计更高明、更稳定测试的精力和时间。这些成本是任何一个需要实施持续交付的团队都得做好心理准备的。

未完成的实践

我们目前还无法基于真实数据设计整个测试、迁移、部署、发布的过程,使用真实数据对于稳定、高质量的验证、部署过程至关重要,但有些棘手的问题让我们无法采用真实数据,比如:

  • 数据库很“大”:10 多年积累下来的数据以 T 记,要想测试必须对数据进行裁剪,如何有效裁剪?因为裁剪不当,我们多次发现因为数据引发的线上问题。
  • 数据库很“敏感”:相对于产品环境,产品数据更加敏感,它往往是一个公司的核心竞争力,各种安全策略保证无法每人都有可以使用这些数据。
  • 数据变化难以“自动化”:开发团队和数据库团队使用不同的工具,对于变化的态度也非常不同,结果是开发团队成熟运用的工具和实践并不能使用到产品环境的数据迁移中,整个审查、验证、应用变化的周期依然漫长,拖慢了产品发布的速度和节奏。

对于其它方面,我们已经有了一套成熟的理论和实践,但对于数据库层面我们还在摸索,也希望看到和听到这方面更多的意见和建议。


感谢张凯峰对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ )或者腾讯微博( @InfoQ )关注我们,并与我们的编辑和其他读者朋友交流。

2012-12-19 07:467989

评论

发布
暂无评论
发现更多内容

MySQL DDL执行方式-Online DDL介绍

京东科技开发者

MySQL 数据库 ddl DML Online DDL

前端如何学习算法?

大师兄

JavaScript 前端算法 9月月更

带你认识全新的华为云IoT路网数字化服务

华为云开发者联盟

云计算 后端 物联网 交通 企业号九月金秋榜

SQL就业市场最吃香!解密为什么SQL历经半个世纪仍经久不衰?

雨果

sql

异步处理 —— RxJS Observable

掘金安东尼

前端 9月月更

CISO 需考虑的五项 Kubernetes 安全措施

SEAL安全

Kubernetes 软件供应链安全

Wiki在企业内部的应用和管理,如何构建有效的Wiki系统?

Baklib

从0到1项目搭建-框架搭建(附源码)

微枫Micromaple

架构 springboot Druid Mybatis-Plus 9月月更

算法基础(三)| 二分图解及代码模板

timerring

算法 二分查找 9月月更

百度交易中台之资产系统架构浅析

百度Geek说

数据库 架构 资产管理

日均数亿推送稳定性监控实践

得物技术

Java 设计模式 重构 SLA 企业号九月金秋榜

慢查询 MySQL 定位优化技巧,从10s优化到300ms

程序知音

Java MySQL 数据库 后端技术 MySQL 数据库

校招 | StarRocks首次Open Day报名ING!

StarRocks

数据库

Github上标星103K的Spring Security实战手册,直接霸榜

程序知音

Java spring 程序员 spring security 后端技术

以Vue为代表的提升小程序开发效率框架及工具

Geek_99967b

小程序

我的C/C++技术成长之路

Fire_Shield

程序人生 C/C++ 9月月更

react面试如何回答才能让面试官满意

beifeng1996

React

阿里云大数据助力知衣科技打造AI服装行业核心竞争力

阿里云大数据AI技术

人工智能 大数据 模型训练 客户案例

“密评”,听说过没

华为云开发者联盟

云计算 网络安全 开发 企业号九月金秋榜

Qt|控件QPushButton讲解

中国好公民st

qt 按钮 9月月更

火山语音7篇论文入选国际顶会Interspeech

科技热闻

如何创建 Angular library 并在生产环境中消费

汪子熙

JavaScript typescript angular library 9月月更

VS Code摸鱼神器,让你快速开发AI模型

华为云开发者联盟

人工智能 企业号九月金秋榜

英伟达NVIDIA为何可以在高性能计算GPU中处于不败地位?

GPU算力

Pipy 同一 IP 多个 SSL 域名

Flomesh

Service Mesh 服务网格

云原生数字化转型与金融信创建设,鱼和熊掌可兼得

BoCloud博云

云计算 云原生 信创

写给自己的react面试题总结

beifeng1996

前端 React

最新MLPerf基准测试:基于阿里云GPU云服务器的AIACC在图像识别封闭式场景下夺冠

阿里云弹性计算

图像识别 GPU实例 AIACC

分布式系统中如何实现临界资源的互斥访问

华为云开发者联盟

云计算 后端 开发 企业号九月金秋榜

羊了个羊闯关游戏开发(链改代币分红)

开发微hkkf5566

MySQL DDL执行方式-Online DDL介绍

京东科技开发者

Java MySQL 数据 ddl DML

互联网行业持续交付的经验_研发效能_胡凯_InfoQ精选文章