发布工程是一个术语,用来描述从存储库中获取代码发布到生产环境中,之间相关的全部过程和所有组件。自动化发布可以帮助避免许多发布工程的传统缺陷: 重复性和手工任务的辛苦、手动流程的不一致性、无法了解上线的确切状态以及回滚困难。发布工程的自动化已经在其他文献中得到了很好的介绍——例如,关于持续集成和持续交付的书籍(CI/CD)。
我们将灰度发布定义为:对服务进行部分且有时间限制的变更部署,并同时进行评估。该评估将帮助我们决定是否继续上线。变更的服务部分是the canary
,服务的其余部分是the control
。支持这种方法的逻辑是,灰度发布通常在线上进行小流量发布,或者影响比the control
部分少得多的用户上。灰度发布是一个有效的A/B测试过程。
我们将首先介绍发布工程的基础知识,以及通过自动化发布来建立共享词汇的益处。
发布工程原理
发布工程的基本原理如下:
可再生构建
构建系统应该能够接受构建输入(源代码、资产等)并生成相同结果。与上周相同的输入(构建代码)应该在本周产生相同的输出。
自动化构建
一旦代码上传之后,能够自动化生成构建组件并将其上传到存储系统。
自动化测试
一旦自动构建系统构建了组件,某种类型的测试套件应该确保它们正常工作。
自动化部署
部署应该由计算机执行,而不是人。
小型部署
构建系统应该支持小的、自包含的更改。
这些原则为运维人员带来直接收益:
- 通过消除手工和重复的任务来减轻工程师的操作负担。
- 强制同行评审和版本控制,因为自动化通常是基于代码的。
- 建立一致的、可重复的、自动化的流程,从而减少错误。
- 添加对发布管道的监控,通过解决以下问题进行测量和持续改进:
- –发布版本需要多长时间生产环境才生效?
- –发布成功的频率是多少?一个成功的版本是一个没有严重缺陷或SLO违规的、客户可用的版本。
- –可以做哪些更改来尽早的捕获管道中的缺陷?
- –哪些步骤可以并行化或进一步优化?
CI/CD与发布自动化相结合可以持续改进开发周期,如图16-1所示。当发布自动化时,你可以更频繁地发布。对于变更率很高的软件来说,更频繁地发布意味着在任何给定的发布工件中捆绑更少的更改。而更小的、自包含的发布工件使得在出现bug时回滚任何给定的发布工件变得成本更低、更容易。更快的发布节奏意味着可以更快地修复bug。
平衡发布速度和可靠性
快速发布(以下称为发布
)和可靠性常常被视为相反的目标。企业希望以100%的可靠性尽快发布新特性和产品改进!然而这个目标是不可能实现的(因为100%从来不是可靠性的正确目标;参见第2章),但可以在满足特定产品的特定可靠性目标的同时,尽可能快地进行交付。
实现这个目标的第一步是了解发布对软件可靠性的影响。在谷歌的经验,大多数事件都是由二进制或配置推送导致的(见附录C)。许多类型的软件更改都可能导致系统故障 - 例如,底层组件的行为更改,依赖关系(例如API)的更改,或DNS等配置更改。
尽管对软件进行变更存在固有的风险,但是这些变更(bug修复、安全补丁和新特性)对业务的成功是必需的。你可以使用SLOs和错误预算的概念来衡量发布新版本对可靠性的影响,而不是提倡反对变更。你的目标应该是在满足用户期望的可靠性目标的同时尽快发布软件。下一节将讨论如何使用canary流程来实现这些目标。
分离变更频率不同的组件
服务由具有不同变更频率的多个组件组成:二进制文件或代码、基础环境(如JVM、内核/OS)、库、服务配置或标志、特性/测试配置和用户配置。如果只有一种发布变更的方法,那么这些组件单独变更会比较困难。
特性标志或测试框架(如Gertrude、Feature和PlanOut)允许你将特性启动从二进制版本中分离出来。如果二进制版本包含多个特性,你可以通过更改测试配置一次启用一个特性。这样,就没有必要将这些小的变更集合为一个大的变更,或者为每个特性执行单独的版本。更重要的是,如果只有一些新特性的行为不像预期的那样,你可以选择性地禁用这些特性,直到下一个构建/发布周期可以部署新的二进制文件为止。
你可以将特性标志/试验原则应用于服务的任何类型的更改,而不仅仅是软件版本。
Canarying是什么?
Canarying
一词是指将金丝雀带入煤矿以确定该矿是否对人类安全的做法。 由于鸟类比人类更小,呼吸更快,因此它们被危险气体毒害的速度比人类更快。
即使你的发布管道是完全自动化的,在真正的流量到达服务之前,你依然无法检测到所有与发布相关的缺陷。当一个发布版本准备好部署到生产环境中时,你的测试策略应该充分保证该版本是安全的,并且按预期工作。然而,测试环境与生产环境并不是100%相同的,并且测试不可能会涵盖100%的场景。依然会存在一些会影响生产缺陷。如果一个版本立即部署到系统的全部地方,那么可能存在的缺陷亦将到达系统的全部地方。
如果你能够快速地检测和解决缺陷,则可以接受此方案。但是,更安全的选择是:首先使用灰度发布向新版本导入一些生产流量。灰度发布允许部署管道在尽可能少地影响你的服务的前提下,更快地检测出问题。
发布工程和灰度发布
在部署系统的新版本或其关键组件(如配置或数据)时,我们将变更(通常未公开给真实输入的更改,如面向用户的流量、或用户提供的批处理数据)打包。变更会带来新的特性和功能,但也存在部署之后出现问题的风险。我们的目标是通过测试一小部分流量来降低风险,以确保没有任何不良影响。我们将在本章后面讨论评估过程。
灰度过程还让我们对变更充满信心,因为我们将其暴露给越来越大的流量。为变更引入实际生产流量还使我们能够识别在单元测试或负载测试等测试框架中可能不可见的问题,这些问题通常更为人为。
我们将使用一个实际的示例来检查灰度过程及其评估,同时避免深入研究统计数据。相反,我们关注点是整个过程和典型的实际考虑。我们使用App Engine上的一个简单应用程序来说明发布的各个方面。
灰度发布流程的需求
针对特定服务的灰度发布需要特定功能:
将变更通过灰度发布部署到服务全部子集的方法。
一个评估过程,用来评估变更是好
还是坏
。
将评估集成到发布过程中。
最后,当灰度检测到有问题的发布版本,并在没有误报的情况下识别出好的发布版本时,灰度发布展示了它的价值。
我们的示例环境
我们将使用一个简单的前端web服务应用程序来演示一些灰度发布的概念。该应用程序提供了一个基于http的API,消费者可以使用它来操作各种数据(如产品价格等简单信息)。示例应用程序有一些可调参数,我们可以使用这些参数来模拟各种生产环境,由灰度发布流程进行评估。例如,可以让应用程序为20%的请求返回错误,或者规定5%的请求至少需要两秒钟。
我们使用部署在谷歌应用程序引擎上的应用程序来演示灰度发布流程,这些原则同样适用于其他环境。虽然示例应用程序是经过设计的,但是在实际场景中,类似的应用程序与我们的示例可以共享灰度发展中使用的指标。
我们的示例服务有两个可能的版本:当前版本和候选版本。当前版本是当前部署在生产环境中的版本,而候选版本是新构建的版本。使用这两个版本来说明发布概念,以及如何实现灰度发布以使发布过程更安全。
回滚部署与简单的Canary部署比较
我们将在发生中断时根据错误预算节省和一般影响,来对没有灰度发布的部署流程和灰度发布流程进行比较。我们的部署过程以开发环境为基础。一旦我们感觉代码在开发环境中正常工作,我们就将该版本部署到生产环境中。
在部署之后不久,监视开始报高错误率(参见图16-2,在图16-2中,为了模拟示例服务中的缺陷,对示例应用程序进行配置以使20%的请求失败)。对于示例,假设部署流程不支持回滚到以前已知的配置正常的版本时。修复这些错误的最佳选择就只有在生产版本中查找缺陷,对其进行补救,并在停机期间重新部署一个新版本。这种做法肯定会延长错误对用户的影响。
为了改进这个初始部署过程,我们可以在使用灰度发布来减少推送错误代码所造成的影响。 我们需要一种方法来在小部分生产环境中运行候选版本,而不是一次性部署到生产环境。 然后将一小部分流量发送到该生产环境(the canary金丝雀)并将其与其他部分(the control 主控)进行比较。 使用此方法,我们可以在所有生产受到影响之前发现候选版本中的缺陷。
我们在示例应用程序中的进行简单灰度发布,在应用程序的特定版本之间分配流量。 您可以使用App Engine或其他任何方法来分割流量(例如负载均衡器上的后端权重,代理配置或循环DNS记录)。
图16-3显示了当我们使用灰度发布,变更的影响会大大降低;事实上,这些错误几乎不可见!这提出了一个有趣的问题:与总体流量趋势相比,灰度发布的流量趋势很难看到和跟踪。
为了更清楚地了解需要在合理范围内跟踪的错误,我们可以通过App Engine应用程序版本查看关键指标(HTTP响应代码),如图16-4所示。当我们查看每个版本的分解趋势图时,我们可以清楚地看到新版本引入的错误。我们还可以从图16-4中观察到当前版本提供的错误非常少。
现在,我们可以根据应用程序版本的HTTP错误率对部署进行调优。如果灰度发布的错误率大于全部系统的错误率,这表明canary部署是糟糕的
。我们应该暂停并回滚部署,或者联系他人来帮助解决问题。如果错误率相似,我们可以正常地进行部署。在图16-4中,我们的canary部署显然很糟糕,我们应该回滚它。
Canary实施
现在我们已经看到了一个相当简单的canary部署实现,接下来让我们更深入地了解成功的canary流程所需的参数。
最小化SLOs和错误预算的风险
第2章讨论了SLOs如何反映设计服务可用性的业务需求。这些需求也可以通过canary实现。canary进程的风险仅仅是我们错误预算的一小部分,它受到时间和canary规模大小的限制。
全局部署会很快将SLO置于危险之中。如果实例中为系统全面部署候选版本,我们将面临20%的请求失败的风险。如果我们使用5%的canary规模,我们将为5%的流量提供20%错误,导致1%的总体错误率(如图16-3所示)。这个策略允许我们保留我们的错误预算—预算的影响与暴露于缺陷的流量的数量成正比。我们可以假设,对于全局部署和灰度部署,检测和回滚花费的时间差不多,但是当我们将灰度发布集成到部署过程中时,我们会以更低的成本获得有关新版本的有价值信息。
这是一个假设负载均匀的极简模型。它还假设我们可以将整个错误预算用于灰度发布。这里我们只考虑新版本引入的不可用性,而不是实际可用性。我们的模型还假设新版本具有100%的失败率,这是最坏的情况。而进行灰度的部分不会导致线上系统100%不可用。我们还允许在灰度部署期间,整个系统的可用性低于SLO。
这个模型有明显的缺陷,但它是一个可靠的起点,你可以根据业务需求进行调整。我们建议使用最简单的模型来满足你的技术和业务目标。根据我们的经验,专注于使模型在技术上尽可能正确,常常会导致在建模上的过度投资。对于具有高复杂性的服务,过于复杂的模型可能导致持续的模型调优,而没有真正的好处。
选择灰度规模和持续时间
选择合适的灰度持续时间,需要考虑发布频率。 如果需要每天发布,那么在一次只运行一个灰度的情况下,无法使灰度保持一周,如果每周部署一次,就可以执行较长的灰度发布。 如果持续部署(例如,一天20次),灰度的持续时间必须明显缩短。 在一些说明里,虽然可以同时运行多个灰度,但这样做会增加大量精力来跟踪系统状态。 在任何情况下,需要快速推断系统状态时,同时运行多个灰度会成为问题。如果灰度重叠,同时运行多个灰度也会增加信号污染的风险。我们强烈建议一次只运行一个灰度。
对于基本的评估,不需要大规模的灰度来检测关键条件。然而,一个有代表性的灰度发布流程需要跨多个维度进行决策:
规模和持续时间
它的规模应够大,持续时间应够长,足以代表整个部署。仅在接收到少量查询后终止canary部署,对于以具有不同功能的不同查询为特征的系统来说,这无法提供有用的信号。处理率越高,获取代表性样本所需的时间就越少,以确保所观察到的行为实际上是由变更引起的,而不仅仅是随机因素。
流量
我们需要在系统上接收足够的流量,以确保它是一个具有代表性的示例,并且系统有机会对输入做出负面反应。通常,请求越均匀,所需要的流量就越少。
时间点
性能缺陷通常只在高负载下出现,因此在非高峰时间部署可能不会触发性能相关的缺陷。
度量指标
灰度的代表性与我们选择评估的指标密切相关(我们将在本章后面讨论)。我们可以快速评估诸如查询成功之类的琐碎指标,但是其他指标(如队列深度)可能需要更多的时间或较大规模的灰度来提供清晰的信号。
但问题是,这些要求可能相互冲突。Canarying是一种平衡行为,它通过对最坏情况的冷静分析和系统过去的实际记录来实现。一旦您从过去的灰度中收集了指标,您就可以根据典型的canary评估失败率而不是假想的最坏情况来选择canary参数。
选择和评估度量标准
到目前为止,我们一直在研究成功率,这是评估灰度发布的一个非常清晰和明显的指标。但是直觉上,我们知道这个单一的指标对于有意义的canary流程来说是不够的。如果我们以10倍的延迟为所有请求提供服务,或者在这样做时使用10倍的内存,那么我们可能也会遇到问题。并不是所有的指标都适合评估灰度发布。哪些指标最适合评估灰度发布版本是好是坏?
度量标准应指出问题
首先,指标需要能够指出服务中的问题。这很棘手,因为构成问题
的并不总是客观的。我们可能会认为用户请求失败是有问题的。但是如果一个请求的响应时间增加了10%,或者系统内存增加了10%?,这该如何判断?我们通常建议使用sla作为开始考虑canary指标的地方。良好的服务质量指数往往与服务健康状况密切相关。如果已经使用SLIs来度量SLO是否符合,那么我们可以重用这些工作。
几乎任何指标在极端情况下都可能出现问题,但是向灰度流程中添加太多的指标也会产生成本。我们需要为每个指标正确定义可接受行为。如果可接受行为定义过于严格,我们会得到大量的误报;也就是说,我们会认为灰度很糟糕,即使实际不是这样。相反,如果对可接受行为的定义过于宽松,我们更有可能忽略掉有问题的灰度部署。正确选择什么是可接受的行为可能会成本较大——既耗时又需要分析。然而,如果做得不好,错误的结果会完全误导你。此外,随着服务、其特性集和行为的发展,您需要定期重新评估期望。
我们应该根据这些指标多大程度上能够表明系统中实际用户的体验来进行排名,选择排名靠前的几个指标(可能不超过12个)。太多的度量标准会带来递减的回报,并且在某种程度上,收益会被维护它们的成本所抵消,或者在发布过程中如果不维护它们,会对发布结果无法保证100%的信任。
为了使这个指导原则更加具体,让我们回头再来看示例。它有许多我们可以评估的指标:CPU使用量、内存占用、HTTP返回码(2xx、3xx等等)、响应延迟、正确性等等。在这种情况下,我们最好的度量标准可能是HTTP返回码和响应延迟,因为它们的降级最接近于实际用户影响。在这个场景中,CPU使用率并没有那么有用:资源使用的增加不一定会影响服务,并且可能导致不稳定或嘈杂的canary进程。这会导致操作人员禁用或忽略canary进程,这会首先破坏使用canary进程的目的。对于前端服务,我们直观地知道,响应较慢或响应失败通常会真实反映服务中存在的问题。
HTTP返回码包含一些有趣的复杂情况,例如状态码404,它告诉我们没有找到资源。这可能是因为用户获得了错误的URL(想象一下在一个流行的论坛上分享了一个错误的URL),或者因为服务器错误地停止了对资源的服务。通常,我们可以通过排除canary评估中的400级状态码,并添加黑盒监控来测试特定URL的存在,从而解决此类问题。然后,我们可以将黑盒数据作为canary分析的一部分,以帮助将canary流程与奇怪的用户行为隔离开来。
度量标准应该具有代表性和可归属性
观察到的指标变化其来源,应该清楚地归因于正在进行的变更,并且不应该受到外部因素的影响。
在一个大的系统中(例如,许多服务器或许多容器),我们可能会有外部性——超过连接的机器、运行具有不同性能特征的不同内核的机器,或者网络中过载的机器。此时金丝雀部分和主系统部分之间的差异,既是我们所部署的两个基础设施之间的差异,也会是我们变更导致的差异。
管理金丝雀是多种力量之间的平衡。增加金丝雀的规模是减少这个问题影响的方法(如前所述)。当我们的系统达到我们认为的合理的金丝雀规模时,我们需要考虑我们选择的指标是否会显示出很大的差异。
我们还应该知道canary和control环境之间共享的失败域;坏金丝雀会对控制产生负面影响,而系统中的坏行为可能会导致我们错误地评估金丝雀。同样,确保您的度量标准是良好隔离的。考虑一个同时运行我们的应用程序和其他进程的系统。整个系统的CPU使用量的急剧增加会导致糟糕的度量,因为系统中的其他进程(数据库负载、日志轮转等)可能会导致这种增加。更好的度量标准是在处理请求时所花费的CPU时间。更好的度量标准是在服务进程实际计划在CPU上的时间窗口上为处理请求服务所花费的CPU时间。虽然与我们的进程相关的严重超额的机器显然是一个问题(监控应该捕捉到它!),但它不是由我们正在进行的更改引起的,因此不应该将其标记为金丝雀部署失败。
金丝雀也需要是可归属的;也就是说,您还应该能够将canary度量与SLIs联系起来。如果一个度量可以在不影响服务的情况下发生巨大变化,那么它不适合用来评估灰度发布。
评估前/评估后依然是有风险的
canary过程的前后是归因问题的延伸。在这个过程中,旧系统被新系统完全替代,你的canary评估将在一段时间内比较变更之前和之后的系统行为。你可以将此过程称为时空中的canary部署
,在此过程中,您通过分割时间来选择A/B组,而不是通过机器、cookie或其他方法来分割总体。由于时间是观察到的指标变化的最大来源之一,因此很难在评估之前/之后来判断性能是否下降。
虽然canary部署可能导致降级,但原有系统本身也可能会降级。如果需要长时间运行canary部署,就会变得更加复杂。例如,如果在周一进行发布,可能会将工作日的行为与周末的行为进行比较,从而引入大量噪音。在该示例中,用户可能在周末以不同的方式访问该服务。从而在canary进程中引入噪音。
评估前/后过程本身引入了一个问题,即大而短的错误率(由前/后评估引入)是否优于小而长的错误率(由一个小金丝雀引入)。如果新版本完全被破坏,我们能多快地检测和恢复? 大规模的金丝雀之前/之后可以更快地检测到问题,但恢复的总体时间可能仍然相当长,与较小的金丝雀类似。在此期间,用户会一直受到影响。
使用渐进的灰度会更好
选择的度量标准即使不符合我们理想中的属性,但仍然很有价值。我们可以通过使用更细微的灰度过程来介绍这些指标。
我们可以使用包含多个阶段的canary来反映我们对度量的推理能力,而不是简单地评估单个canary阶段。在第一阶段,我们对这个版本没有信心或不了解。因此,我们希望使用一个小的阶段,以尽量减少负面影响。在小型灰度中,我们更喜欢能够最清晰地显示问题的指标——应用程序崩溃、请求失败等等。一旦这一阶段成功地过去,下一阶段将增加灰度规模,从而增强我们分析变化影响的信心。
依赖和隔离
正在测试的系统不会在完全真空中运行。出于实际原因,灰度和主系统可以共享后端、前端、网络、数据存储和其他基础设施。甚至可能与客户端有非常不明显的交互。例如,假设一个客户端发送了两个连续的请求。第一个请求可以由灰度部分来处理。其响应可能会改变第二个请求的内容,第二个请求可能会落在主系统部分,从而改变主系统的行为。
不完美的隔离会带来几个后果。最重要的是,我们需要知道,如果灰度过程的结果表明我们应该停止生产变更并调查情况,那么灰度并不一定是错误的。这一事实对于一般的canarying来说是正确的,但是在实践中,它经常由于隔离问题而导致被强制执行。
此外,不完美的隔离意味着灰度部署的错误行为也会对原始系统产生负面影响。Canarying是A/B比较,A和B有可能同时改变;这可能会导致评估灰度变得混乱。还必须使用绝对度量,例如定义的SLOs,以确保系统正确运行。
在非交互系统中进行Canarying
本章重点讨论了交互式请求/响应系统,它在许多方面是最简单和最常讨论的系统设计。其他系统,如异步处理管道,也同样重要,但有不同的canarying注意事项,我们将简要列举。有关数据处理管道的canarying的更多信息,请参见第13章。
首先,canary的持续时间和部署本质上依赖于工作单元处理的持续时间。当涉及到交互系统时,我们忽略了这个因素,假设工作单元处理的时间不会超过几秒钟,这比canary的持续时间要短。非交互式系统中的工作单元处理(如呈现管道或视频编码)可能需要更长的时间。因此,确保canary持续时间至少跨越单个工作单元的持续时间。
对于非交互式系统,隔离可能变得更加复杂。许多管道系统只有一个工作分配程序和一组使用应用程序代码的工作人员。在多阶段管道中,工作单元由工作人员处理,然后返回到池中,由同一工作人员或另一个工作人员执行下一阶段的处理。金丝雀分析有助于确保处理特定工作单元的工人总是从相同的工人池中提取——要么是金丝雀池,要么是控制池。否则,信号就会变得越来越混杂(有关理清信号的需要的更多信息,请参见349页的监视数据的要求
)。
最后,度量标准的选择可能更加复杂。我们可能感兴趣的是端到端处理工作单元的时间(类似于交互系统中的延迟),以及处理本身的质量(当然,这是完全特定于应用程序的)。
考虑到这些警告,canarying的一般概念仍然是可行的,并且适用相同的高级原则。
监控要求
在评估灰度部署时,您必须能够将部署了灰度的系统与未部署灰度的系统进行比较。通常,这需要在构造监视系统时多加注意—有效的比较非常简单,并且能够产生有意义的结果。
考虑之前的例子,在5%的规模中进行灰度,错误率为20%。因为监视很可能将系统作为一个整体来观察,所以它只能检测到1%的总体错误率。根据系统的不同,这个信号可能与其他错误源无法区分(参见图16-3)。
如果我们通过按照服务请求的对象来(金丝雀与主系统)分解指标,(参见图16-4)我们可以清楚地看到主系统与canary之间的错误率,这清楚地说明了全局部署将带来什么。在这里,我们看到,对整个服务的监控不足以分析灰度是否ok。在收集监视数据时,能够执行细粒度的分解非常重要,这些分解使得能够区分金丝雀和主系统的指标。
收集指标的另一个难点是金丝雀的部署受到设计的时间限制。当度量指标在特定时期内进行聚合时,这可能会导致问题。考虑每小时的度量误差。我们可以通过对过去一小时的请求求和来计算这个度量。如果我们使用这个度量来评估我们的canary,我们可能会遇到问题,如下面的时间表所述:
- 某些事件会导致一些错误发生。
- 一只金丝雀被部署在5%的人口中;金丝雀的持续时间是30分钟。
- canary系统开始监视每小时的错误度量,以确定部署是好是坏。
- 部署被检测为错误,因为每小时的错误度量与控制总体的每小时的错误显著不同。
此场景是使用每小时计算一次的度量来评估仅30分钟长的部署的结果。因此,canary进程提供了一个非常模糊的信号。当使用度量来评估canary的成功时,确保度量的间隔与canary的持续时间相同或小于持续时间。
相关概念
通常,与客户的对话涉及到在生产中使用蓝/绿部署、人工负载生成和/或流量测试。这些概念类似于canarying,因此虽然它们不是严格意义上的金丝雀流程,但亦可使用。
蓝/绿部署
蓝/绿部署维护系统的两个实例:一个提供流量(绿色),另一个准备提供流量(蓝色)。 在蓝色环境中部署新版本后,将流量切换到其中。切换过程不需要停机,并且回滚只是简单逆转路由器而已。 一个缺点是该设置使用的资源是传统
部署的两倍。在该设置中,您正在有效地执行前/后金丝雀(前面已讨论过)。
通过同时(而不是分开地)使用蓝/绿部署,您可以或多或少地将蓝色/绿色部署用作常规的金丝雀。在此策略中,您可以将canary部署到blue(备用)实例,并在绿色和蓝色环境之间缓慢地分配流量。您的评估和比较蓝色环境和绿色环境的指标都应该与流量控制相关。这种设置类似于A/B金丝雀,此时绿色环境是主系统,蓝色环境是金丝雀部署,金丝雀数量由发送到每个金丝雀的流量控制。
人工负载生成
与其将实时用户流量暴露给canary部署,还不如在安全性方面犯点错误,使用人工负载。通常,您可以在多个部署阶段(QA、预生产,甚至在生产中)运行负载测试。虽然根据我们的定义,这些操作不符合canarying,但是它们仍然是找到缺陷的可行方法,但需要注意一些事项。
使用人工负载进行测试可以很好地最大化代码覆盖率,但不能提供良好的状态覆盖率。在可变系统(具有缓存、cookie、请求关联等的系统)中人工模拟负载尤其困难。人工负载也可能无法准确地模拟真实系统中流量变化。有些问题可能只在无人工负载的情况下出现,从而导致覆盖率有所差距。
人工负载在可变系统中也很难工作。例如,试图在计费系统上生成人工负载可能非常危险:系统可能开始向信用卡供应商发送呼叫,然后信用卡供应商将开始主动向客户收费。虽然我们可以避免测试危险的代码逻辑,但是在这些逻辑上缺乏测试会降低我们的测试覆盖率。
流量测试
如果人工流量不具有代表性,我们可以复制流量并将其发送到生产系统和测试环境。这种技术被称为流量镜像。生产系统服务于实际流量并响应请求,canary部署服务于副本流量并丢弃响应。您甚至可以将canary响应与实际响应进行比较,并运行进一步的分析。
这种策略可以提供有代表性的流量,但通常比更直接的canary流程更复杂。在有状态系统中,流量测试也不能充分识别风险;流量副本可能会在看似独立的部署之间引入意外的影响。例如,如果canary部署和生产系统共享一个缓存,人为导致的缓存命中率增加将使canary指标的性能度量无效。
结论
您可以使用许多工具和方法来自动化版本发布,并将canarying引入到发布管道中。没有一种测试方法是万能的,测试策略应该由系统的需求和行为决定。Canarying可以作为一种简单、健壮且易于集成的方法来补充测试。当您及早发现系统缺陷时,用户受到的影响最小。Canarying还可以为频繁发布提供信心,并提高开发速度。正如测试方法必须随着系统需求和设计而发展一样,canarying也必须如此。