+
豆瓣广告系统持续发布相关的实践
大家好,我是来自豆瓣网的测试工程师,张伟,
今天要和大家分享的话题是豆瓣广告系统在持续集成方面的相关实践。
下面是我的邮箱还有微博,欢迎大家关注和线下交流
+
How fast we can?
+
agenda
产品背景基本介绍
从测试出发,持续集成
持续集成运用于开发周期各阶段
持续发布相关实践
今天的话题主要分四个方面,
首先是产品背景的基本介绍;
其次我们项目从测试出发,如何开始接触CI也就是持续集成系统,,
然后是如何讲持续集成运用在开发周期中的各阶段
最后介绍下我们现阶段进行持续发布的相关实践
+
产品概要
豆瓣广告系统
内容
文本广告
音频
视频
平台
Web
App
那我先来介绍一下豆瓣广告系统
在坐的有用过豆瓣电台吗?有的请举下手,看来我们公司的外部广告还不够多。如果不是pro用户,一定能听到广告
豆瓣的广告投放系统包含,广告的投放,计划,展示,数据收集功能。
广告类型有文本、音频、视频等,
对应的平台有web端和移动端等。
+
技术背景
广告投放系统
投放策略系统
投放引擎
监控系统
我们的广告系统主要分为以下几个子系统:
广告投放系统:就是广告需求的整理和汇合,对于一个广告来说,我们通过广告投放系统来整理素材(比如说一个广告的文字,图片,音频,视频),根据客户的需求:如展示位,关键词,投放的日期,地域等条件生成对应的广告订单。
投放策略系统:我们通过投放系统的广告订单,经过算法的计算,生成相关投放策略。
广告投放引擎:实际执行相关投放策略,展示广告,记录用户的访问和点击数
监控系统:统计相关广告订单的运行状态和整个广告系统的运行状态,实时反馈。
我们今天主要讲的是豆瓣投放引擎
+
Development Environment init
Long doc for env init
fab
fab _config:
Ref
豆瓣投放引擎是用纯Go语言实现的广告投放引擎。
我是中途加入到这个项目的,在我加入前这个项目应该做了大半年了吧。
进入新项目一开始的熟悉工作是搭环境。
这个项目有份巨长的文档介绍如何搭环境,我照着文档逐行弄了半天!
豆瓣主站其实很早就开始使用持续集成系统;而在我进入项目组的时候,这个项目是相关unittest了,但是一直没有加入到持续集成中。
我问开发为什么不放到CI里面?
他们回答:环境的建立太麻烦!我心想,能不麻烦吗!我搭环境对着文档都弄了半天。
所以进入项目做的第一件事就是简化开发环境的搭建。
我们用了python的构建工具fab来做这件事情,因为豆瓣是python用得比较重的公司,而fab在公司之前的很多的项目中有使用。
对于一个如Go一样新的语言,用上之前已经有积累而且很熟悉的工具,往往可以事半功倍。
右边就是现在的情况
+
Fab as tasks tool
我们使用了fab作为构建工具,这页是我们构建工具的命令列表
简化了日常的开发,测试;从预发布到发布,甚至工具,所有的操作都可以用简单的命令来完成。
程序员最讨厌的两件事情是:写文档和别人不写文档。。。
很多时候,文字手册往往写了一版,随着代码的更新,过一阵子就过时了。
而构建工具其实就是手册,活的手册。我们可以通过阅读代码来了解每个构建的详细步骤。
,随着代码的更新,实时更新构建命令,因为你不更新就执行不了相关的操作,所以这份构建工具作为文档是最新的;
+
Remote import package
Ref:
Remote import
目录中的package
那我们再回到go语言
go语言的包管理工具支持直接引用外部包,如balbla的相关包
Go语言自带的包管理工具,每次都会将依赖包下载到指定目录
这是go语言的一个非常好的feature,如果A引用了B,B更新的时候也会更新A;
+
OuT OF CoNTRoL
Ref
但是对于持续集成或者上线系统来说,这并不是一个好feature
如果外部包更新了每次构建的结果都不可控。
之前就有一次提交代码运后相关测试失败了,开发调试了半天没找出问题,然后回滚后依然失败,又弄了半天,最后才发现是依赖包更新了
世界上最遥远的距离不是生与死,而是你亲手制造的BUG就在你眼前,你却怎么都找不到她。。。
+
Package by reversion
我们的解决方案是:将依赖用指定版本号管理。
用fab重写了go语言外部依赖包安装程序,指定各外部依赖的版本,确保了只要代码版本不变,每次构建结果都一致。
如果需要更新相关的依赖包,修改版本号即可。
这样使得测试和发布变得可控,每次编译出来的二进制包都是一致的
+
初涉CI,从测试出发
Go Lang
Fab as tasks tool
Remote import package by reversion
CI for master
go2xunit
前面说到的都是开发环境相关的内容,我们用fab作为构建工具,简化了创建环境的步骤。
我们将外部依赖变得可控,提高了构建的稳定性。
这些工作都是为了之后的测试做准备。
来到这个项目的时候,已经有了相关的单元测试。
环境搭好,测试也准备好,很自然的我们将相关单元测试放到了CI中运行;
我们还引入了go2unit,生成兼容xunit的测试报告,供CI解析结果
+
CI for Master
GUI
Tests
Unit Test
API Tests
之前提到,我们已经有了一部分的单元测试,补充了更多的用例,,单测执行时间短,运行稳定,是所有测试类型的基础。
广告投放引擎其实就是对外提供相关接口,根据访问的页面,账户ip等输入信息的不同,推送不同的广告。
所以针对接口,我们补充了api相关的测试。API测试的特点是测试时间较长,因为每次都需要编译和启动服务,访问相关的HTTP接口;也没有单元测试那么稳定。
而广告最终是对用户呈现,针对页面的实际的渲染,我们补充了一部分GUI的case,查看浏览器兼容性,检查含广告的页面的显示等操作。
最终的结构像同金字塔般将测试分层, 单元测试最多,但是运行时间最短;
Api测试次多,运行时间适中。
GUI的测试最少,仅包含基本内容,运行的时间最长。
我们把针对主干的各种测试类型放入了持续集成系统,
每次代码的提交,CI都会运行相关的编译和单元测试和api测试,保证系统的基本功能。
我们也鼓励开发在提交前,在本地做相关的构建和测试,但是仅是鼓励,不做政策上的要求。
+
Configuration management
有人又想到了,不做相关的要求,岂不是很容易把主干的CI搞挂,没关系,我们有别的方法
先说下我们是用的版本管理系统。
在豆瓣我们主要用中央式的svn 和分布式的git 来管理源代码,这两种版本管理系统估计大家日程工作中也在用。
根据不同版本管理系统,我们使用不同开发工作流。
+
Subversion Feature Branch
Test for Branch
Ref
对于subversion,我们一般采用feature branch的工作流。
为新的功能从主干创建的特性分支,几个同事在同一个分支里提交代码;一般持续几天到数周;
期间如果主干有大的改动,还会merge出新的分支。一直到功能开发完成,再merge回主干
这种工作流有什么问题?
持续一段时间才和主干合并,在开发过程中,并不知道是否可发布,甚至不知道是否可运行。
所有的问题集中在最后merge会trunk的那一刹那,出了问题开发修得很紧张,其它想上线的人也要等他修复完毕。很狼狈。
+
CI for SVN branch
Create continuous build job for branch update
Publish failed build result to developer
我们做了什么?
我们自动为每个分支创建了相关的持续构建,就是之前分层金字塔包含的测试类型。让开发的每次提交都有快速反馈。不需要等到最后merge的时候手忙脚乱。
然后我们过滤了相关的提醒,只向dev发送失败的提醒。最大限度的不影响开发。
我们发现code review一直推不起来,很多人一次push 一大坨代码,基本上没法review,因为太多太长了!
曾经看到一个code review有一百多次提交,基本上没人看
很多人说code review要占用他们一大块的时间,每周都要抽出一个下午进行组内的review。
针对特性分支的问题,然后我们引入了github Flow也叫做Pull Request Flow。
+
Github (Pull Request) flow
Master branch is deployable
Create a descriptively named branch off of master
Commit to that branch locally and push to the server
When you need feedback or help, or branch is ready for merging, open a pull request
After reviewed and signed off on the feature, merge it into master
After merged, deploy immediately
ref:
随着分布式代码管理工具的流行,我们开始使用Git,其实更早用的是Mercurial。
无论是Mercurial或者git,我们一开始的使用方式都是和之前svn feature branch类似,给开发开通相关权限,大家提交后push到对应的branch里。
区分是否程序员的方法之一:push的反义词是什么? 非程序员:pull ;程序员:pop。
然后我们引入了github Flow也叫做Pull Request Flow。
什么是Github Flow?简单来说包含以下几点要求。
首先,master分支是要时刻保证可发布的状态
其次,创建的分支名需要含义清楚
然后,每次提交到本地分支后push回server端
当需要反馈或者帮助,更多的情况是分支准备好被merge,提交一个PR
当代码被review完并且停止更新后,merge会master分支
Merge后,直接发布
+
CI for github flow
针对github flow我们也引入了持续集成相关的内容,
我们会在每次提交Pull Request的时候执行相关测试,如果测试通过可以进入下一步merge,
如果测试失败,则开发修复后提交更新。然后重复这个步骤,直到测试通过。
这就是我们现在的例子
举例我提交了一个新的feature,一般来说就是几次commit,若干代码
当他想要merge回master,提交了一个Pull Request,
CI执行相关各种类型的测试,给出测试结果
同时相关的同事的review代码,评论和吐槽,
开发根据相关反馈,提交更新,自动构建新的测试
测试通过后,merge按钮变绿,就可以汇入主干了。
Continuous Deployment
From Continuous Integration to
前面两种工作流相关,其实想分享一个观点:就是测试的投资回报率。
当测试用例的开发,维护成本相对稳定之后,通过持续集成系统,在工作流的各个阶段,测试执行的次数越多,投资回报率越高。
而由于时间,成本的关系。我们不能做到100%的测试覆盖率。
但是我们能提供持续的测试反馈,我们确保了系统的基本功能可用。
保证系统基本可用之后我们要干什么?当然是发布上线。
只有更早的上线才能更早的触发问题,更快的修复。实现持续交付。
+
环境的隔离
三个环境是隔离的
开发环境
+
Monitor
Test & Build
Deploy
PreRelease
Push Data
Pre release
After merged
代码提交进主干之后会经历几个步骤?我们会自动部署到预发布环境。大体的过程是这样的
master执行相关测试,只编译生成一份二进制包
测试、编译通过自动发布到预发布环境;
上到预发布环境后,相关数据初始化和推送。
最后是通过监控系统来查看相关日志和报告。
出现了问题,解决问题,提交新的更新继续步骤。
流程看起没什么ok?查看相关问题只需到监控系统看log和report就能发现并修复了。
但是有个问题,相关的log和report都是需要用例来触发的,比如很多问题需要访问广告页面才能触发
预发布环境如何提供相关的用例触发问题?
Pre-release: traffic, traffic
Nn%
NN:与主站的pre-release联动
nn%
Nn:tcpcopy 流量复制
N:手工检查页面
n%
如何增加用例,
手工检查页面,很简单的方法,我需要什么用例,就提供相关的输入输出,但是这样产生的用例成本较高,用例数也比较少
我们又想还有什么的别的方法能更省力吗?连接到主站的预发布系统,因为我们的广告主要显示在豆瓣主站的页面,我们预发布和主站的预发布环境联动,这样通过别的项目开发过程中的访问,触发我们的用例,用例变多了,省时省力。但是覆盖率不够高,比如地域相关的用例就不能触发出来,因为开发都在一个地方工作。
如何做到全部的覆盖呢?我们使用了流量复制工具,开源的tcpcopy,用线上的单台服务器的访问复制导入到预发布环境中,触发出了所有用例。
所以说预发布环境和线上最大的区别是流量的问题,有了流量,预发布环境才更有意义。
+
Deploy Flow
我们再展开下整个上线流水线的过程,这些操作都是在持续集成系统中完成
所谓的流水线,必然是上下游有同一的交付物
我们的交付物是二进制包,在build之后生成的二进制包供之后的apitest使用,二进制包按版本号命名
当测试通过,也是同一份二进制包发布到预发布环境,之前的二进制包也保留。
最后的发布到线上,手工选择发布特定经过上面流水线检验的二进制包,并且选定特定的服务器,集群,上线。
不是不能做到当预发布测试检查通过之后自动自动化,而是将发布这个权利交还给用户;因为持续部署是一种能力,是一种自信,能让人喝茶的时候上线,选择什么时候上线,在哪上线,闲庭信步。
+
Binary file
Only one file
Version as filename
Keep old files
+
Deployment
Single Node
Cluster
All server
如同预发布环境
发布到线上也类似,逐渐增加流量,
按流量分为单机,集群,所有服务器
+
5 %
Single Node
再回到
单机发布,意义不是很大,特别是预发布环境的验证充分之后
很多时候是为了验证某些功能在线上环境和线上数据、配置是否ok
+
Cluster
40 %
而按cluster发布
更多的是算法或者性能用来做相关的对比。
通过不同的开关,经过一段时间的观察,对比效果
+
100 %
All Servers
整站发布则是现在发布的常态,
当持续发布的相关设施搭建完毕后,可以将发布按钮的权限交给整个团队的任何人
那天开发还和我说,有了上线系统,我发现现在上线都是整站上线了?我问为什么?
因为回滚容易了
+
Configuration service
Cluster Configuration Files in git
Pull Request
Push Configuration to cluster
Notification
Via
广告投放系统有很多相关的配置,比如db,mc的连接信息,各种功能的开关,之前这些东西都散落在各个服务器,每次手工修改都很麻烦,就算用上相关工具也麻烦。
而且还有一个问题:一人修改其它人还不知道,每次都是修改完了,上线了,其他人通过数据看出相关问题。
后来我们将配置文件放到了git来管理,每次的修改通过PR的方式来提交,提交所有人review相关的更改。
我们还做了个配置推送系统,当merge后,自动推送到各个服务器完成配置更新。之后这个系统还会推送数据。
配置更新后irc通知大家,所有的修改都有迹可循。
+
Monitoring
Graph
QPS
ERROR
All in one
LOG
REPORT
DUTY
Notification
监控其实是持续发布非常重要的一环,有了监控才有反馈环
我们通过相关的图表可视化系统信息,各服务的QPS器响应时间的error,等信息,没什么比看图更直观的
将所有需要关注的项目汇合在一起,详细的log,各广告的报告,各cluster心跳、每周也有相关的值日生记录和解决问题。
通过图表,log提供了非常丰富的信息,但是不需要每条都看,我们只关心哪里出了问题,当有了问题 短信、irc、email全方位轰炸。
有了反馈系统,一旦出错,立即反馈,趁工程师还记得修改了什么,能很快修复;如果短时间修复不了,那就快速的点击rollback。
所以说不怕出问题,就怕不知道怎么更早的触发问题和解决问题。
+
Summary
补充测试
持续集成
Master
branch
自动部署预发布和线上环境
模拟了访问量
配置和数据推送
监控作为反馈
+
Q&A
大家好,我是来自豆瓣网的测试工程师,张伟,
今天要和大家分享的话题是豆瓣广告系统在持续集成方面的相关实践。
下面是我的邮箱还有微博,欢迎大家关注和线下交流
今天的话题主要分四个方面,
首先是产品背景的基本介绍;
其次我们项目从测试出发,如何开始接触CI也就是持续集成系统,,
然后是如何讲持续集成运用在开发周期中的各阶段
最后介绍下我们现阶段进行持续发布的相关实践
那我先来介绍一下豆瓣广告系统
在坐的有用过豆瓣电台吗?有的请举下手,看来我们公司的外部广告还不够多。如果不是pro用户,一定能听到广告
豆瓣的广告投放系统包含,广告的投放,计划,展示,数据收集功能。
广告类型有文本、音频、视频等,
对应的平台有web端和移动端等。
我们的广告系统主要分为以下几个子系统:
广告投放系统:就是广告需求的整理和汇合,对于一个广告来说,我们通过广告投放系统来整理素材(比如说一个广告的文字,图片,音频,视频),根据客户的需求:如展示位,关键词,投放的日期,地域等条件生成对应的广告订单。
投放策略系统:我们通过投放系统的广告订单,经过算法的计算,生成相关投放策略。
广告投放引擎:实际执行相关投放策略,展示广告,记录用户的访问和点击数
监控系统:统计相关广告订单的运行状态和整个广告系统的运行状态,实时反馈。
我们今天主要讲的是豆瓣投放引擎
豆瓣投放引擎是用纯Go语言实现的广告投放引擎。
我是中途加入到这个项目的,在我加入前这个项目应该做了大半年了吧。
进入新项目一开始的熟悉工作是搭环境。
这个项目有份巨长的文档介绍如何搭环境,我照着文档逐行弄了半天!
豆瓣主站其实很早就开始使用持续集成系统;而在我进入项目组的时候,这个项目是相关unittest了,但是一直没有加入到持续集成中。
我问开发为什么不放到CI里面?
他们回答:环境的建立太麻烦!我心想,能不麻烦吗!我搭环境对着文档都弄了半天。
所以进入项目做的第一件事就是简化开发环境的搭建。
我们用了python的构建工具fab来做这件事情,因为豆瓣是python用得比较重的公司,而fab在公司之前的很多的项目中有使用。
对于一个如Go一样新的语言,用上之前已经有积累而且很熟悉的工具,往往可以事半功倍。
右边就是现在的情况
我们使用了fab作为构建工具,这页是我们构建工具的命令列表
简化了日常的开发,测试;从预发布到发布,甚至工具,所有的操作都可以用简单的命令来完成。
程序员最讨厌的两件事情是:写文档和别人不写文档。。。
很多时候,文字手册往往写了一版,随着代码的更新,过一阵子就过时了。
而构建工具其实就是手册,活的手册。我们可以通过阅读代码来了解每个构建的详细步骤。
,随着代码的更新,实时更新构建命令,因为你不更新就执行不了相关的操作,所以这份构建工具作为文档是最新的;
那我们再回到go语言
go语言的包管理工具支持直接引用外部包,如balbla的相关包
Go语言自带的包管理工具,每次都会将依赖包下载到指定目录
这是go语言的一个非常好的feature,如果A引用了B,B更新的时候也会更新A;
但是对于持续集成或者上线系统来说,这并不是一个好feature
如果外部包更新了每次构建的结果都不可控。
之前就有一次提交代码运后相关测试失败了,开发调试了半天没找出问题,然后回滚后依然失败,又弄了半天,最后才发现是依赖包更新了
世界上最遥远的距离不是生与死,而是你亲手制造的BUG就在你眼前,你却怎么都找不到她。。。
我们的解决方案是:将依赖用指定版本号管理。
用fab重写了go语言外部依赖包安装程序,指定各外部依赖的版本,确保了只要代码版本不变,每次构建结果都一致。
如果需要更新相关的依赖包,修改版本号即可。
这样使得测试和发布变得可控,每次编译出来的二进制包都是一致的
前面说到的都是开发环境相关的内容,我们用fab作为构建工具,简化了创建环境的步骤。
我们将外部依赖变得可控,提高了构建的稳定性。
这些工作都是为了之后的测试做准备。
来到这个项目的时候,已经有了相关的单元测试。
环境搭好,测试也准备好,很自然的我们将相关单元测试放到了CI中运行;
我们还引入了go2unit,生成兼容xunit的测试报告,供CI解析结果
之前提到,我们已经有了一部分的单元测试,补充了更多的用例,,单测执行时间短,运行稳定,是所有测试类型的基础。
广告投放引擎其实就是对外提供相关接口,根据访问的页面,账户ip等输入信息的不同,推送不同的广告。
所以针对接口,我们补充了api相关的测试。API测试的特点是测试时间较长,因为每次都需要编译和启动服务,访问相关的HTTP接口;也没有单元测试那么稳定。
而广告最终是对用户呈现,针对页面的实际的渲染,我们补充了一部分GUI的case,查看浏览器兼容性,检查含广告的页面的显示等操作。
最终的结构像同金字塔般将测试分层, 单元测试最多,但是运行时间最短;
Api测试次多,运行时间适中。
GUI的测试最少,仅包含基本内容,运行的时间最长。
我们把针对主干的各种测试类型放入了持续集成系统,
每次代码的提交,CI都会运行相关的编译和单元测试和api测试,保证系统的基本功能。
我们也鼓励开发在提交前,在本地做相关的构建和测试,但是仅是鼓励,不做政策上的要求。
有人又想到了,不做相关的要求,岂不是很容易把主干的CI搞挂,没关系,我们有别的方法
先说下我们是用的版本管理系统。
在豆瓣我们主要用中央式的svn 和分布式的git 来管理源代码,这两种版本管理系统估计大家日程工作中也在用。
根据不同版本管理系统,我们使用不同开发工作流。
对于subversion,我们一般采用feature branch的工作流。
为新的功能从主干创建的特性分支,几个同事在同一个分支里提交代码;一般持续几天到数周;
期间如果主干有大的改动,还会merge出新的分支。一直到功能开发完成,再merge回主干
这种工作流有什么问题?
持续一段时间才和主干合并,在开发过程中,并不知道是否可发布,甚至不知道是否可运行。
所有的问题集中在最后merge会trunk的那一刹那,出了问题开发修得很紧张,其它想上线的人也要等他修复完毕。很狼狈。
我们做了什么?
我们自动为每个分支创建了相关的持续构建,就是之前分层金字塔包含的测试类型。让开发的每次提交都有快速反馈。不需要等到最后merge的时候手忙脚乱。
然后我们过滤了相关的提醒,只向dev发送失败的提醒。最大限度的不影响开发。
我们发现code review一直推不起来,很多人一次push 一大坨代码,基本上没法review,因为太多太长了!
曾经看到一个code review有一百多次提交,基本上没人看
很多人说code review要占用他们一大块的时间,每周都要抽出一个下午进行组内的review。
针对特性分支的问题,然后我们引入了github Flow也叫做Pull Request Flow。
随着分布式代码管理工具的流行,我们开始使用Git,其实更早用的是Mercurial。
无论是Mercurial或者git,我们一开始的使用方式都是和之前svn feature branch类似,给开发开通相关权限,大家提交后push到对应的branch里。
区分是否程序员的方法之一:push的反义词是什么? 非程序员:pull ;程序员:pop。
然后我们引入了github Flow也叫做Pull Request Flow。
什么是Github Flow?简单来说包含以下几点要求。
首先,master分支是要时刻保证可发布的状态
其次,创建的分支名需要含义清楚
然后,每次提交到本地分支后push回server端
当需要反馈或者帮助,更多的情况是分支准备好被merge,提交一个PR
当代码被review完并且停止更新后,merge会master分支
Merge后,直接发布
针对github flow我们也引入了持续集成相关的内容,
我们会在每次提交Pull Request的时候执行相关测试,如果测试通过可以进入下一步merge,
如果测试失败,则开发修复后提交更新。然后重复这个步骤,直到测试通过。
这就是我们现在的例子
举例我提交了一个新的feature,一般来说就是几次commit,若干代码
当他想要merge回master,提交了一个Pull Request,
CI执行相关各种类型的测试,给出测试结果
同时相关的同事的review代码,评论和吐槽,
开发根据相关反馈,提交更新,自动构建新的测试
测试通过后,merge按钮变绿,就可以汇入主干了。
前面两种工作流相关,其实想分享一个观点:就是测试的投资回报率。
当测试用例的开发,维护成本相对稳定之后,通过持续集成系统,在工作流的各个阶段,测试执行的次数越多,投资回报率越高。
而由于时间,成本的关系。我们不能做到100%的测试覆盖率。
但是我们能提供持续的测试反馈,我们确保了系统的基本功能可用。
保证系统基本可用之后我们要干什么?当然是发布上线。
只有更早的上线才能更早的触发问题,更快的修复。实现持续交付。
三个环境是隔离的
开发环境
代码提交进主干之后会经历几个步骤?我们会自动部署到预发布环境。大体的过程是这样的
master执行相关测试,只编译生成一份二进制包
测试、编译通过自动发布到预发布环境;
上到预发布环境后,相关数据初始化和推送。
最后是通过监控系统来查看相关日志和报告。
出现了问题,解决问题,提交新的更新继续步骤。
流程看起没什么ok?查看相关问题只需到监控系统看log和report就能发现并修复了。
但是有个问题,相关的log和report都是需要用例来触发的,比如很多问题需要访问广告页面才能触发
预发布环境如何提供相关的用例触发问题?
如何增加用例,
手工检查页面,很简单的方法,我需要什么用例,就提供相关的输入输出,但是这样产生的用例成本较高,用例数也比较少
我们又想还有什么的别的方法能更省力吗?连接到主站的预发布系统,因为我们的广告主要显示在豆瓣主站的页面,我们预发布和主站的预发布环境联动,这样通过别的项目开发过程中的访问,触发我们的用例,用例变多了,省时省力。但是覆盖率不够高,比如地域相关的用例就不能触发出来,因为开发都在一个地方工作。
如何做到全部的覆盖呢?我们使用了流量复制工具,开源的tcpcopy,用线上的单台服务器的访问复制导入到预发布环境中,触发出了所有用例。
所以说预发布环境和线上最大的区别是流量的问题,有了流量,预发布环境才更有意义。
我们再展开下整个上线流水线的过程,这些操作都是在持续集成系统中完成
所谓的流水线,必然是上下游有同一的交付物
我们的交付物是二进制包,在build之后生成的二进制包供之后的apitest使用,二进制包按版本号命名
当测试通过,也是同一份二进制包发布到预发布环境,之前的二进制包也保留。
最后的发布到线上,手工选择发布特定经过上面流水线检验的二进制包,并且选定特定的服务器,集群,上线。
不是不能做到当预发布测试检查通过之后自动自动化,而是将发布这个权利交还给用户;因为持续部署是一种能力,是一种自信,能让人喝茶的时候上线,选择什么时候上线,在哪上线,闲庭信步。
如同预发布环境
发布到线上也类似,逐渐增加流量,
按流量分为单机,集群,所有服务器
再回到
单机发布,意义不是很大,特别是预发布环境的验证充分之后
很多时候是为了验证某些功能在线上环境和线上数据、配置是否ok
而按cluster发布
更多的是算法或者性能用来做相关的对比。
通过不同的开关,经过一段时间的观察,对比效果
整站发布则是现在发布的常态,
当持续发布的相关设施搭建完毕后,可以将发布按钮的权限交给整个团队的任何人
那天开发还和我说,有了上线系统,我发现现在上线都是整站上线了?我问为什么?
因为回滚容易了
广告投放系统有很多相关的配置,比如db,mc的连接信息,各种功能的开关,之前这些东西都散落在各个服务器,每次手工修改都很麻烦,就算用上相关工具也麻烦。
而且还有一个问题:一人修改其它人还不知道,每次都是修改完了,上线了,其他人通过数据看出相关问题。
后来我们将配置文件放到了git来管理,每次的修改通过PR的方式来提交,提交所有人review相关的更改。
我们还做了个配置推送系统,当merge后,自动推送到各个服务器完成配置更新。之后这个系统还会推送数据。
配置更新后irc通知大家,所有的修改都有迹可循。
监控其实是持续发布非常重要的一环,有了监控才有反馈环
我们通过相关的图表可视化系统信息,各服务的QPS器响应时间的error,等信息,没什么比看图更直观的
将所有需要关注的项目汇合在一起,详细的log,各广告的报告,各cluster心跳、每周也有相关的值日生记录和解决问题。
通过图表,log提供了非常丰富的信息,但是不需要每条都看,我们只关心哪里出了问题,当有了问题 短信、irc、email全方位轰炸。
有了反馈系统,一旦出错,立即反馈,趁工程师还记得修改了什么,能很快修复;如果短时间修复不了,那就快速的点击rollback。
所以说不怕出问题,就怕不知道怎么更早的触发问题和解决问题。