金丝雀发布、滚动发布、蓝绿发布到底有什么差距?关键点是什么?
根据2017年的devops发展报告,高效能组织和低效能组织在软件交付的效率上有数量级上的差异。技术组织的软件交付能力是一种综合能力,设计众多环节,其中发布是尤为重要的环节。
作为技术人员,大家可能听过“滚动发布”和“蓝绿发布”等术语,但是很多人并不清楚这些术语背后的原理。本文试图总结当前主流的发布策略,每个的优劣,适用性,让开发人员特别是架构师对现代发布技术有一个更为清晰全面的认识,让大家能够认识自己的企业上下文,对发布策略做出正确的选型和实践。
单服务器组发布
先解释下单服务器组的概念,早先我们机器资源比较紧张,不像现在云计算和虚拟化(包括容器技术)这么发达,所以应用机器基本是预先静态分配好的(一般是由运维负责分配),原来应用A住在n台机器上,那么下次升级发布的应用A也住在这n台机器上,所以称为单台服务器组发布方式。
1.1蛮力发布
如下图所示,这种发布方式比较简单粗暴,有点像我们传统的软件升级方式,主要靠手工完成,先将老版本V1全部下掉,再将新版本发不到机器上去。这种方式会引入服务中断(停机),在开发测环境中是可行的,但是对于生产环境发布,其会直接影响用户的使用体验,这种方式一般是不建议的。
优势和适用场合
优势
简单成本低
不足
服务汇中断用户受影响,出现了问题回退也慢
适用场合
开发测试环境
非关键应用(用户影响小)
初创公司什么都缺,找夜深人静用户访问量小的时间干
流量模式
蛮力发布会引入服务中断时间。
金丝雀发布(单组服务器组)
在蛮力发布基础上的一种简单改进发布方式,目前仍然是不少成长型技术组织的主流发布方式。单租服务器组下的金丝雀发布的简化步骤如下图所示:
实践要点
1、金丝雀发布一般先发布1台,或者一个小比例,例如2%的服务器,主要做流量验证用,也称为金丝雀(canary)测试(国内常称灰度发布)。以前矿工开矿下矿洞前,先会放一只金丝雀进去探是否有毒气,看金丝雀是否能活下来,金丝雀发布由此得名。简单的金丝雀发布测试一般通过手工测试验证,复杂的金丝雀测试需要比较完善的监控基础设施配合,通过监控指标反馈,观察金丝雀的健康状况,作为后续发布或者回退的依据。
2、如果金丝雀测试通过,则把剩余的V1版本全部升级为V2版本。如果金丝雀测试失败,则直接退回金丝雀,发布失败。
优势和适用场合
优势
用户体验影响小,金丝雀发布过程中出现问题只影响少量用户
不足
发布自动化程度不够,发布期间可能应发服务中断
适用场合
对新版本或性能缺乏足够自信心,求稳定
用户体验要求较高的网站业务场景
缺乏足够的自动化发布工具研发能力
流量模式
少量金丝雀先接受流量,再全量发布。
滚动式发布(单服务器组)
在金丝雀发布基础上的进一步优化改进,是一种自动化程序较高的发布方式,用户体验比较平滑,是目前成熟型技术组织所采用的主流发布方式。单服务器组下的滚动发布的简单步骤如下图所示
发布中,先发一台金丝雀
发布中,再发若干台
直到全部发完
实践要点
1、滚动式发布一般是先发布1台,或者一个很小的比例,比如2%的服务器,主要做流量验证用,类似金丝且(canary)测试
2、滚动式发布需要比较复杂的发布工具和智能LB,支持平滑的版本替换和流量拉入拉出
3、每次发布时。先将老版本V1流量从LB上摘除,然后清除老版本,发布新版本V2,再将LB流量接入新版本,每次这样尽量保证用户体验不受影响。
4、一次滚动式发布一般由若干个发布批次组成,每批次的数量一般是可以配置的(可以通过发布模板定义)。
例如第一批1台(金丝雀),第二批10%,第三批50%,第四批100%。每个批次之间留观察间隔,通过手工验证或者监控反馈确保没有问题再发布下一批次,所以总体上发布过程是比较缓慢的(其中金丝雀的时间一般会比后续批次更长,比如金丝雀10分钟,后续间隔2分钟)。
5、回退是发布的逆过程,将新版本流量从LB上摘除,清除新版本,发布老版本,再将LB流量接入老版本,和发布过程一样,回退过程一般也比较慢。
6、滚动式发布国外术语通常叫rolling update deployment。
优势和适用场合
优势
用户体验影响小,体验较平滑
不足
发布和回退时间比较慢
发布工具比较复杂,LB需要平滑的流量摘除和拉入能力
适用场合
用户体验不能中断的网站业务场景
有一定的复杂工具研发能力
流量模式
双服务器组发布
随着云计算和虚拟化技术的成熟,特别是容器等轻级虚拟化技术的引入,计算资源受限和申请缓慢问题以及逐步解决,可以做到弹性按需分配。为一次分布分配两组服务器,一组运行现有的V1老版本,一组运行待上线的V2新版本,再通过LB切换流量方式完成发布,这就是所谓的双服务器组发布方式。
蓝绿发布(双组服务器组)
蓝绿发布仅适用于双服务器组发布,可以认为是对蛮力发布的一种简单优化发布方式。简化过后层如下图所示:
滚动式发布(双服务器组)
滚动式发布是对上面的蓝绿和金丝雀发布的进一步优化,按批次增量滚动发布,提供更平滑的用户体验。
实践要点
1、发布前先申请一批新服务器,数量一般和V1版本相同,将V2版本应用发布到新服务器上。例如如果在AWS云上,则可以直接调用API申请一批新VM,如果用容器kubernetes,则可以直接启动一批新容器(使用V2版本容器镜像)。
2、一般会先通过LB拉入1台V2版本的机器,这台机器也相当于金丝雀,用于流量验证。
3、逐步按批次完成发布,每批只需要通过LB拉入V2版本,再拉出对应数量的V1版本。批次之间保留有观察间隔,通过手工或监控反馈确保没有问题再继续发布。
4、发布有问题回退很快,直接通过LB将流量切回V1即可。
5、完成发布后,一般V1版本要保留观察以备万一,比如留1天,1天后没有问题则回收V1机器资源。
优势和适用场合
优势
用户体验影响小
升级切换和回退速度比单服务器组滚动发布更快,LB切换流量即可。
不足
需要两倍机器资源
发布工具比较负责,LB需要流量切换能力
适用场合
用户体验不能中断的网站业务场景
机器资源富有或者可以按需分配(AWS或者自建容器云)
有一定的发布工具研发能力
流量模式
其他发布方式
上述都是偏传统的发布方式,能覆盖大部分应用发布场景。针对一些关键新功能的上线发布,或者一些特定的场景,还有一些特殊的发布方式。
功能开关发布
利用代码中的功能开关(Feature Flag/Toggle/Switch)来控制发布逻辑,一般不需要复杂的发布工具和智能 LB 配合,是一种相对比较低成本和简单的发布方式。这种方式也是支持现代 DevOps 理念,研发人员可以灵活定制和自助完成的发布方式。功能开关的原理如下图所示:
实践要点
1、功能开关发布需要一个配置中心或者开关中心这样的服务支持,例如携程的 Apollo 配置中心附录 6.3,或者开源的 FF4J附录 6.4,这些都支持开关发布,业界还有专门的功能开关 SaaS 服务,例如 LaunchDarkly附录 6.5。通过配置中心,运维或研发人员可以在运行期动态配置功能开关的值。当然,功能开关发布只是配置中心的一种使用场景,配置中心还能支持其它很多动态配置场景。
2、功能开关服务一般提供客户端 SDK,方便开发人员集成。在运行期,客户端 SDK 会同步最新的开关值,技术实现有推方式 (push),也有拉方式 (pull),或者推拉结合方式。
3、新功能(V2 new feature)和老功能(V1 old feature)住在同一套代码中,新功能隐藏在开关后面,如果开关没有打开,则走老代码逻辑,如果开关打开,则走新代码逻辑。技术实现上可以理解为一个简单的 if/else 逻辑。
4、应用上线后,开关先不打开,然后运维或研发人员通过开关中心打开新功能,经过流量验证新功能没有问题,则发布完成;如果有问题,则随时可以通过开关中心切回老功能逻辑。
优势和适用场合
优势
升级切换和回退速度
相对复杂的发布工具,实施比较简单,成本相对低廉
研发能够灵活定制发布逻辑,支持devops自助发布
不足
切换是全量的,如果V2版本有问题,则对用户体验有直接影响
对代码有入侵,代码逻辑会变复杂,需要定期清理老版本逻辑,维护成本高
适用场合
用户体验有一定容忍度的场景
已有配置中心或开关中心服务
暂不具备研发复杂发布工具能力
流量模式
A/B 测试
A/B 测试附录 7.10原来主要用于产品功能的比对测试,收集用户反馈和对比数据做产品功能设计的决策。实际上,A/B 测试也可以作为一种新功能发布技术。下图展示基于 LB 实现的一种 A/B 测试发布。
实践要点
1、上图中,原来 PC 端和手机端都访问老版本 V1 服务(也称 A 组或控制组),当 V2 新版本(也称 B 组或实验组)发布以后,为了验证 V2 的功能正确性,同时也为了避免 V2 有问题时影响所有用户,先通过 LB 将手机端的流量切换到 V2 版本,经过一段时间的 A/B 比对测试和观察(主要通过用户和监控反馈),确保 V2 正常,则通过 LB 将全部流量切换到 V2。
2、基于 LB 方式实现 A/B 测试,LB 需要能够通过某种条件做流量路由,例如通过 client ip,设备类型,浏览器类型,甚至是定制的 HTTP Header 或查询字符串。
3、高级的 A/B 测试需要专门的平台支撑,wasabi附录 6.6就是 intuit 开源的一个支持高级 A/B 测试的平台,这类平台可以细粒度到针对某类用户做 A/B 测试,例如针对某个地区的用户,某个年龄段的用户,公司内部用户等等。举了例子,假设一个关键业务的新功能上线,为了降低风险采用 A/B 测试,可以做到先只让公司内部员工能访问到新功能,待新功能验证过,再全量放开给外部用户使用。
4、功能开关和 A/B 测试有点相似,但功能开关一般是无状态和全量的,无法做到针对某类特定用户进行测试,而 A/B 测试一般是有状态的,能够跟踪事务和用户级别的状态,可以实现针对某类特定用户进行测试。
优势和适用场合
优势
用户体验影响小
可以使用生产流量测试;
可以做到针对某类特定目标用户进行测试;
不足
搭建复杂度相对高,有一定技术门槛
适用场合
核心关键业务,比如涉及资金的
具备一定的 A/B 测试平台研发能力
流量模式
影子测试
对于一些涉及核心业务的遗留系统的升级改造,为了确保万无一失,有一种称为影子测试的大招,采用比较复杂的流量复制、回放和比对技术实现。下面是影子测试的一个样例架构图
实践要点
1、目标实现老的 legacy 服务迁移升级到新的 experimental 服务。
2、测试开始前,需要在测试环境部署一份 legacy 服务和 experimental 服务,同时将生产数据库复制两份到测试环境。同时需要将生产请求日志收集起来,一般可以通过 kafka 队列收集,然后通过类似 goreplay附录 6.8这样的工具,消费 kafka 里头的请求日志,复制回放,将请求分发到 legacy 服务和 experimental 服务,收到响应后进行比对,如果所有响应比对成功,则可以认为 legacy 服务和 experimental 服务在功能逻辑上是等价的;如果有响应比对失败,则认为两者在功能逻辑上不等价,需要修复 experimental 并重新进行影子测试,直到全部比对成功。根据系统复杂度和关键性不同,比对测试时间短的可能需要几周,长的可达半年之久。
3、影子测试因为旁路在独立测试环境中进行,可以对生产流量完全无影响。
4、影子测试一般适用于遗留系统的等价重构迁移,例如.net 转 Java,或者 SQLServer 数据库升级为 MySQL 数据库,且外部依赖不能太多,否则需要开发很多 mock,测试部署成本会很高,且比对测试更加复杂和不稳定。
5、当当网有一个比较成功的交易系统.NET 转 Java 迁移项目附录 6.9,采用了影子测试技术,值得参考借鉴。
优势和适用场景
优势
对生产用户体验完全无影响
可以使用生产真实流量进行测试(复制比对)
不足
搭建复杂度很高,技术门槛高,数据库的导出复制是难点
外部依赖不能太多,否则测试部署成本很高,且比对测试更加复杂和不稳定
适用场合
核心关键业务,比如涉及资金的
具备一定影子测试平台研发能力,包括流量复制、数据库导出复制和分发比对系统。
流量模式
比较
结论和建议
下面是对发布策略的一些选型建议,供不同阶段公司参考:
1、蛮力发布一般是不建议采用的,除非是开发测试环境,用户体验不敏感的非关键应用,或者是创业期什么都缺时候的无奈之举。
2、如果暂时还不具备研发较复杂的滚动发布工具和配套智能 LB,则功能开关是一种不错的轻量级发布技术,投入相对较小的成本,可以让研发人员灵活定制发布逻辑。
3、金丝雀发布通过少量新版本服务器接收生产流量的方式去验证新版本,可以显著降低风险。金丝雀发布适用于大部分场景,一般成长型公司就可以采用。
4、对于达到一定业务体量的公司,考虑到用户体验对业务的关键性,则需要投入研发资源开发支持滚动式发布的工具和配套的智能 LB,实现自动化和零停机的发布。滚动式发布一般和金丝雀发布配合,先发一台金丝雀去验证流量,再按批次增量发布。
5、随着轻量级虚拟化(例如容器)的普及,双服务器组发布方式具有更快的发布和回退速度,是值得投入的高级发布技术。蓝绿部署仅适用于双服务器组,滚动式发布既可以在单服务器组上实现,也可以在双服务器组上实现。
6、对于涉及关键核心业务的新功能上线,采用 A/B 测试,可以显著降低发布风险,A/B 测试是唯一一种支持针对特定用户组进行生产测试的高级发布技术。当然 A/B 测试的投入不低,建议有一定研发能力的组织采用。
7、对于关键核心业务的迁移重构,为确保万无一失,最后的一个大招是影子测试,影子测试对生产流量和用户完全无影响。当然这个大招的投入成本和门槛都高,建议有足够业务体量和研发能力的组织投入。
8、上述的各种发布策略并不是非此即彼的,一个公司常常会综合采用多种发布技术作为互补,实现灵活的发布能力。例如主流的发布手段是金丝雀 + 滚动式发布,某些业务线可能根据业务场景需要采用功能开关发布,还有一些业务线则可能采用高级的 A/B 测试发布手段。