服务发布策略
文章目录
软件产品环境
一个软件产品从开发到用户使用都涉及哪些环境?
开发环境、测试环境、回归环境、预发布环境、生产环境。
下面说说我个人对这些环境的理解:
开发环境
顾名思义,开发同学开发时使用的环境,每位开发同学在自己的dev分支上干活,提测前或者开发到一定程度,各位同学会合并代码,进行联调。
测试环境
也就是测试同学干活的环境啦,一般会由测试同学自己来部署,然后在此环境进行测试。bug修复后,需要发版更新测试环境来回归bug。
预发布环境
测试环境到生产环境的过渡。测试环境可能会受到一些限制,一些流程或者数据没有测试到,就可以在预发布环境进行验证,从而保证产品上线质量。
web项目的预发布环境,一般是单独部署一个代码节点,连接的是生产环境的资源,比如DB,Cache,队列等。通过地址参数,cookie,请求头参数,vpn等方式,让测试人员可以接入这个特定的环境,做正式发布前的整体回归测试。然后还可以在负载均衡层面,接入小部分真实用户流量,观察性能变动和用户反馈,可以确定是否存在隐藏的性能问题和没有测试出来的bug。
最典型的预发布环境测出来的一个bug示例:生产环境代码更新到最新版本了,但是数据库的变更忘了在生产数据库操作。这个情况下,测试环境很可能都是正常的,但是预发布环境就可以很好的抓到bug。
特点:
- 预发布环境不能被线上用户访问
- 预发布环境和线上环境公用数据库,即预发布环境使用的是线上的数据库.
这里,因为预发布环境本身就是线上环境,测试完预发布,也基本代表线上环境测试完成。这样还可以避免发布到正式环境还得再测一遍的情况
灰度环境
灰度发布,发生在预发布环境之后,生产环境之前。
生产环境一般会部署在多台机器上,以防某台机器出现故障,这样其他机器可以继续运行,不影响用户使用。灰度发布会发布到其中的几台机器上,验证新功能是否正常。如果失败,只需回滚这几台机器即可。
生产环境
即线上环境,用户使用的环境。由特定人员来维护,一般人没有权限去修改。
发布策略
应用程序升级面临最大挑战是新旧业务切换,将软件从测试的最后阶段带到生产环境,同时要保证系统不间断提供服务。
蓝绿发布
简介
蓝绿发布的目的是减少发布时的中断时间、能够快速撤回发布。
蓝绿发布中,一共有两套系统:一套是正在提供服务系统,标记为“绿色”;另一套是准备发布的系统,标记为“蓝色”。两套系统都是功能完善的,并且正在运行的系统,只是系统版本和对外服务情况不同。
最初,没有任何系统,没有蓝绿之分。
然后,第一套系统开发完成,直接上线,这个过程只有一个系统,也没有蓝绿之分。
后来,开发了新版本,要用新版本替换线上的旧版本,在线上的系统之外,搭建了一个使用新版本代码的全新系统。 这时候,一共有两套系统在运行,正在对外提供服务的老系统是绿色系统,新部署的系统是蓝色系统。
蓝色系统不对外提供服务,用来做啥?
用来做发布前测试,测试过程中发现任何问题,可以直接在蓝色系统上修改,不干扰用户正在使用的系统。(注意,两套系统没有耦合的时候才能百分百保证不干扰)
蓝色系统经过反复的测试、修改、验证,确定达到上线标准之后,直接将用户切换到蓝色系统:
切换后的一段时间内,依旧是蓝绿两套系统并存,但是用户访问的已经是蓝色系统。这段时间内观察蓝色系统(新系统)工作状态,如果出现问题,直接切换回绿色系统。
当确信对外提供服务的蓝色系统工作正常,不对外提供服务的绿色系统已经不再需要的时候,蓝色系统正式成为对外提供服务系统,成为新的绿色系统。 原先的绿色系统可以销毁,将资源释放出来,用于部署下一个蓝色系统。
小结
从过程不难发现,在部署的过程中,我们的应用始终在线。并且新版本上线的过程中,并没有修改老版本的任何内容,在部署期间,老版本的状态不受影响,这样风险很小。并且只要老版本的资源不被删除,理论上,我们可以在任何时间回滚到老版本。
注意事项
当你切换到蓝色环境时,需要妥当处理未完成的业务和新的业务。如果你的数据库后端无法处理,会是一个比较麻烦的问题。
- 可能会出现需要同时处理微服务架构应用和传统架构应用的情况,如果在蓝绿部署中协调不好这两者,还是有可能会导致服务停止。
- 需要提前考虑数据库与应用部署同步迁移/回滚的问题。
- 蓝绿部署需要有基础设施支持。
- 在非隔离基础架构(VM,Docker等)上执行蓝绿部署,蓝色环境和绿色环境有被摧毁的风险。
优势和不足
优势:
- 升级切换和回退速度非常快。
不足:
- 切换是全量的,如果 V2 版本有问题,则对用户体验有直接影响。
- 需要两倍机器资源。
适用场合
- 对用户体验有一定容忍度的场景。
- 机器资源有富余或者可以按需分配(AWS 云,或自建容器云)。
金丝雀发布
简介
金丝雀发布(Canary)也是一种发布策略,和国内常说的灰度发布是同一类策略。
蓝绿发布是准备两套系统,在两套系统之间进行切换,金丝雀策略是只有一套系统,逐渐替换这套系统。
譬如说,目标系统是一组无状态的Web服务器,但是数量非常多,假设有一万台。
这时候,蓝绿发布就不能用了,因为你不可能申请一万台服务器专门用来部署蓝色系统(在蓝绿发布的定义中,蓝色的系统要能够承接所有访问)。
可以想到的一个方法是:
只准备几台服务器,在上面部署新版本的系统并测试验证。测试通过之后,担心出现意外,还不敢立即更新所有的服务器。 先将线上的一万台服务器中的10台更新为最新的系统,然后观察验证。确认没有异常之后,再将剩余的所有服务器更新。
这个方法就是金丝雀发布。
实际操作中还可以做更多控制,譬如说,给最初更新的10台服务器设置较低的权重、控制发送给这10台服务器的请求数,然后逐渐提高权重、增加请求数。
这个控制叫做“流量切分”,既可以用于金丝雀发布,也可以用于后面的A/B测试。
蓝绿发布和金丝雀发布是两种发布策略,都不是万能的。有时候两者都可以使用,有时候只能用其中一种。
上面的例子中可以用金丝雀,不能用蓝绿,那么什么时候可以用蓝绿,不能用金丝雀呢?整个系统只有一台服务器的时候。
名词解释
灰度期:灰度发布开始到结束期间的这一段时间,称为灰度期。
灰度发布引擎:对于一般的小系统并不需要单独的灰度发布引擎,可以参考A/B测试中做法,在页面javascript或服务器端实现分流的规则即可。但对于大型的互联网应用而言,单独的用于管理用户分流的发布引擎就很有必要了。
用户标识:用于区分用户,辅助数据统计,保证灰度发布过程中用户体验的连贯性(避免用户在新旧版本中跳变,匿名Web应用比较容易有这个问题)。匿名Web应用可采用IP、Cookie等,需登录的应用可直接采用应用的帐号体系。
目标用户选取策略:即选取哪些用户先行体验新版本,是强制升级还是让用户自主选择等。强制升级可考虑的因素很多,包括但不限于地理位置、用户终端特性、用户自身特点等。用户自主选择,让用户自主选择采用stable、beta、unstable channel的版本。在用户有明确预期的情况下自行承担试用风险。
数据反馈:用户数据反馈:在得到用户允许的前提下,收集用户的使用新版本应用的情况。如客户端性能、客户端稳定性、使用次数、使用频率等。用于与旧版本进行对比,决策后续是继续扩大新版本投放范围还是回滚。服务端数据反馈:新版本服务端性能、服务端稳定性等,作用与用户数据反馈类似。
新版本公关运营支持:对于改版级别的大型升级,需要配合公关运营支持,用于及时处理用户在微博、博客等渠道给出的“显式反馈”。对比通过隐式数据反馈得到的结论后,综合考虑应对策略。
方案探讨
预发布机
其实这个不是真正意义上的灰度。因为这个预先发布机器是内部IP,没有对外服务的。需要绑定域名进行验证。但是数据是完全的线上。所以本质上是灰度某些特定用户(可以访问灰度机器的用户,内部测试用户)的一种简单做法。其实API这边也有类似的做法,就是我们的Gamma环境,而且我们还提供了Gamma机器的域名,方便外部合作用户配合测试。
优点
- 简单
缺点
- 浪费一台机器(这个可以预先发布完成之后投入正式环境,预发布的时候从nginx摘除,不过需要运维支持。)
- 不够灵活
- 只能针对接入层机器,IDL服务灰度需要另外考虑。
SET部署
按照业务隔离部署
比如现在API Container的做法,部署的粒度可以到API级别,前端根据nginx进行转发。比如:
- 微购物 API Container: api.weigou.qq.com
- 拍拍 API Container:api.paipai.com
- 易迅 API Container: api.yixun.com
- 网购 API Container:api.buy.qq.com
上面是大业务级别的隔离部署。还可以进一步细化到模块级别,比如虚拟服务电商的API,是挂在拍拍下面的一个子业务模块,但是由于他们接入微信之后,访问量大增,为了避免影响拍拍其他业务,也为了避免受其他业务影响,API这里是给他们单独部署了两台机器,nginx配置一下就可以将针对虚拟的API访问引流过来了:
虚拟API Container:http://api.paipai.com/v2/virbiz
这样,我们在发布一个版本的时候,可以先选择业务量最小的易迅进行发布,观察没有问题再全量其他平台。
按照用户隔离部署
这个对于开放平台来说不是很适合,不过对于SNS这种应用场景就很合适了。比如QQ系统,按照用户号码段分为若干个set,每个set包含连续1亿个号码的用户。假设现在最新的QQ号码接近10亿,则总共有10个set(Set 1到Set 10)。这样每次可以选择其中一个SET进行发布,而且高位QQ往往是不是很重要的用户,所以会先发布SET10。
优点
- 隔离部署,各个业务线影响最小。自动支持灰度发布。
缺点
- 灰度的粒度取决于隔离部署的粒度,一般会偏大。
- 相对于集中部署比较浪费机器。
- 各个业务线版本可能不一致,不利于统一管理。
- 有一定的实现和部署成本
数据库的灰度升级
比如SqlServer迁移到MySQL,或者数据库字段修改。
- 首先数据全量复制,双写
- 再双写一段时间
- 去掉旧版本的DB,只写新数据库
滚动发布
简介
在金丝雀发布基础上的进一步优化改进,是一种自动化程度较高的发布方式,用户体验比较平滑,是目前成熟型技术组织所采用的主流发布方式。
定义:
滚动发布:一般是取出一个或者多个服务器停止服务,执行更新,并重新将其投入使用。周而复始,直到集群中所有的实例都更新成新版本。
特点:
这种部署方式相对于蓝绿部署,更加节约资源——它不需要运行两个集群、两倍的实例数。我们可以部分部署,例如每次只取出集群的 20% 进行升级。
部署过程:
- 滚动式发布一般先发 1 台,或者一个小比例,如 2% 服务器,主要做流量验证用,类似金丝雀 (Canary) 测试。
- 滚动式发布需要比较复杂的发布工具和智能 LB,支持平滑的版本替换和流量拉入拉出。
- 每次发布时,先将老版本 V1 流量从 LB 上摘除,然后清除老版本,发新版本 V2,再将 LB 流量接入新版本。这样可以尽量保证用户体验不受影响。
- 一次滚动式发布一般由若干个发布批次组成,每批的数量一般是可以配置的(可以通过发布模板定义)。例如第一批 1 台(金丝雀),第二批 10%,第三批 50%,第四批 100%。每个批次之间留观察间隔,通过手工验证或监控反馈确保没有问题再发下一批次,所以总体上滚动式发布过程是比较缓慢的 (其中金丝雀的时间一般会比后续批次更长,比如金丝雀 10 分钟,后续间隔 2 分钟)。
- 回退是发布的逆过程,将新版本流量从 LB 上摘除,清除新版本,发老版本,再将 LB 流量接入老版本。和发布过程一样,回退过程一般也比较慢的。
优势和不足
优势:
- 用户体验影响小,体验较平滑。
不足:
- 发布和回退时间比较缓慢。
- 发布工具比较复杂,LB 需要平滑的流量摘除和拉入能力。
功能开关发布
简介
利用代码中的功能开关(Feature Flag/Toggle/Switch)来控制发布逻辑,一般不需要复杂的发布工具和智能 LB 配合,是一种相对比较低成本和简单的发布方式。这种方式也是支持现代 DevOps 理念,研发人员可以灵活定制和自助完成的发布方式。功能开关的原理如下图所示:
部署过程:
- 功能开关发布需要一个配置中心或者开关中心这样的服务支持,例如携程的 Apollo 配置中心或者开源的 FF4J,这些都支持开关发布。业界还有专门的功能开关 SaaS 服务,例如 LaunchDarkly。通过配置中心,运维或研发人员可以在运行期动态配置功能开关的值。当然,功能开关发布只是配置中心的一种使用场景,配置中心还能支持其它很多动态配置场景。
- 功能开关服务一般提供客户端 SDK,方便开发人员集成。在运行期,客户端 SDK 会同步最新的开关值,技术实现有推方式 (push),也有拉方式 (pull),或者推拉结合方式。
- 新功能(V2 new feature)和老功能(V1 old feature)住在同一套代码中,新功能隐藏在开关后面,如果开关没有打开,则走老代码逻辑,如果开关打开,则走新代码逻辑。技术实现上可以理解为一个简单的 if/else 逻辑。
- 应用上线后,开关先不打开,然后运维或研发人员通过开关中心打开新功能,经过流量验证新功能没有问题,则发布完成;如果有问题,则随时可以通过开关中心切回老功能逻辑。
优势和不足
优势:
- 升级切换和回退速度非常快。
- 相对于复杂的发布工具,实施比较简单,成本相对低廉。
- 研发能够灵活定制发布逻辑,支持 DevOps 自助发布。
不足:
- 切换是全量的,如果 V2 版本有问题,则对用户体验有直接影响。
- 对代码有侵入,代码逻辑会变复杂,需要定期清理老版本逻辑,维护成本变高。
测试机制
A/B测试
首先需要明确的是,A/B测试和蓝绿发布以及金丝雀,完全是两回事。
蓝绿发布和金丝雀是发布策略,目标是确保新上线的系统稳定,关注的是新系统的BUG、隐患。
A/B测试是效果测试,同一时间有多个版本的服务对外服务,这些服务都是经过足够测试,达到了上线标准的服务,有差异但是没有新旧之分(它们上线时可能采用了蓝绿发布的方式)。
A/B测试关注的是不同版本的服务的实际效果,譬如说转化率、订单情况等。
A/B测试时,线上同时运行多个版本的服务,这些服务通常会有一些体验上的差异,譬如说页面样式、颜色、操作流程不同。相关人员通过分析各个版本服务的实际效果,选出效果最好的版本。
在A/B测试中,需要能够控制流量的分配,譬如说,为A版本分配10%的流量,为B版本分配10%的流量,为C版本分配80%的流量。
影子测试
简介
对于一些涉及核心业务的遗留系统的升级改造,为了确保万无一失,有一种称为影子测试的大招,采用比较复杂的流量复制、回放和比对技术实现。下面是影子测试的一个样例架构图:
部署过程:
影子测试一般适用于遗留系统的等价重构迁移,例如 .net 转 Java,或者 SQLServer 数据库升级为 MySQL 数据库,且外部依赖不能太多,否则需要开发很多 mock,测试部署成本会很高,且比对测试更加复杂和不稳定。
- 目标实现老的 legacy 服务迁移升级到新的 experimental 服务。
- 测试开始前,需要在测试环境部署一份 legacy 服务和 experimental 服务,同时将生产数据库复制两份到测试环境。同时需要将生产请求日志收集起来,一般可以通过 kafka 队列收集,然后通过类似 goreplay 这样的工具,消费 kafka 里头的请求日志,复制回放,将请求分发到 legacy 服务和 experimental 服务,收到响应后进行比对,如果所有响应比对成功,则可以认为 legacy 服务和 experimental 服务在功能逻辑上是等价的;如果有响应比对失败,则认为两者在功能逻辑上不等价,需要修复 experimental 并重新进行影子测试,直到全部比对成功。根据系统复杂度和关键性不同,比对测试时间短的可能需要几周,长的可达半年之久。
影子测试因为旁路在独立测试环境中进行,可以对生产流量完全无影响。
优势和不足
优势:
- 对生产用户体验完全无影响。
- 可以使用生产真实流量进行测试(复制比对)。
不足:
- 搭建复杂度很高,技术门槛高,数据库的导出复制是难点。
- 外部依赖不能太多,否则测试部署成本很高,且比对测试更加复杂和不稳定。
参考: http://blog.sina.com.cn/s/blog_13cc013b50102wkog.html https://blog.csdn.net/moakey/article/details/78917516 https://www.zhihu.com/question/42160474/answer/183593313 https://www.lijiaocn.com/%E6%96%B9%E6%B3%95/2018/10/23/devops-blue-green-deployment-ab-test-canary.html http://www.yunweipai.com/archives/25338.html https://www.jianshu.com/p/bd9aa22be357 http://arganzheng.life/gray-release.html https://juejin.im/post/5d02d881f265da1b695d59f4
文章作者 Forz
上次更新 2020-03-03