本文是“为规模而设计”系列文章的第3部分。一定要阅读第1部分——重写是正确的,第二部分建立你需要的东西, 和一部分4-Deployment惊喜

第1部分第2部分在这个系列中,我讨论了如何New Relic的见解团队计划并实现了对我们的高吞吐量面向客户的API服务的替换,即遗留Insights自定义事件插入器(ICEI)。为了创建一个更可靠和可维护的软件系统,我们选择在Ratpack,一个现代的异步HTTP请求处理框架。

当我们执行应用程序时,我们使用Ratpack的可测试性来创建一个深入的单元测试框架,以验证我们所有的功能需求,包括修复遗留系统中存在的bug。剩下的就是将其扩大到生产就绪状态。

最后10%是90%

在新的遗物规模上操作软件时,“功能完整”和“准备生产”之间存在巨大差异。正如我在本系列第2部分所述,我们在两周内建立了遗留ICEI的替代品,此时它是完整的。它采取了另一个团队两个月为生产规模的操作准备软件。这听起来可能是很长的一段时间,但是操作系统所需的努力通常会使构建系统所需的努力相形见绌。

同样在第2部分中,我讨论了吞吐量和有效负载大小需求,以及我们如何使用新的遗物Java代理并对遗留生产系统所看到的有效载荷分布形状进行分析。我们知道,我们的替代者也必须满足同样的要求。准备生产冰证需要我们这样做证明系统已经准备好了我们发布了它。

这是为了确保不会因为转换而丢失或破坏客户数据。事实上,我们希望向新ICEI的过渡对我们的客户完全透明。如果我们努力工作,我们的客户永远不会注意到有什么不同。

但是,您如何证明系统可以在将该系统运送到生产环境之前处理生产环境的需求?

大规模的负载和压力测试

我们预先知道了ICEI所需的性能规格,因为我们有现成的系统中的所有生产性能数据New Relic APM和见解。为了正确地测试生产的负载和应力条件,我们需要在受控环境中模拟生产负载特性。

理想情况下,应力和负载测试将使用实际生产数据进行。当考虑为ICEI进行压力测试时,团队最初打算分叉生产数据,并将其并发发送到遗留系统和ICEI。这种方法将允许我们直接比较两个系统插入的数据,以确定它们是否表现出相同的行为。

在New Relic,我们的数据吸收管道有很大的影响力Apache卡夫卡一个开源的数据消息队列系统,为高吞吐量和高可靠性而设计。与New Relic使用Kafka的系统不同,ICEI通过HTTP接受数据上传。Kafka允许多个消费者从相同的队列中读取数据,这使得遗留系统和替换系统能够并行工作,并且消费相同的数据。

但是,由于ICEI是KAFKA生产者,而不是消费者,双重调度对两个系统的请求需要攻击数据流并将其分派给两个系统进行处理。攻击新I​​CEI的数据流将需要修改传统ICE,以通过HTTP重播其所有输入到新实现。

我们认为这太冒险了,所以Insights团队需要一个替代的方法。我们仍然必须将系统置于与生产环境中的遗留ICEI所看到的负载相当的负载下,但是我们不能对真实数据进行双重调度。鉴于这些限制,我们需要构建一个人工负载发生器来运行和测试新系统。

生成人工负载并不一定困难,因为有许多可用的工具可以完成这项工作。但是,仅仅生成一个负载还不足以验证系统是否已经为生产做好了准备。只是生成一个均布荷载接近生产环境的吞吐量将证明该系统可以维持交通,但不会表面更深层次的信息,如软件如何回应高度可变的条件下,处理过程中产生的各种各样的错误条件,或发生在什么系统放置在胁迫下由于基础设施的问题。为了提供对负载响应的有用度量,负载本身需要尽可能接近地模拟生产中看到的条件。

如果你回忆起第2部分,Insights团队使用直方图功能的力量New Relic查询语言(NRQL),我们强大的SQL-icS查询语言,以确定在我们的生产环境中遗留系统看到的有效载荷大小的分布:

NRQL直方图示例

我们利用这些数据设计了一个负载发生器,它可以在相同的分布中产生有效负载,并使我们能够调整到越来越大的容量。然后,我们在用于监控新ICEI的仪表板上包含了生成的有效载荷大小的柱状图。使用一个仪表板,我们可以在被测试系统处理的有效负载的直方图旁边显示负载生成器的直方图,并很容易地判断行为是否符合我们的预测。

到目前为止,我专注于负载测试。同样重要的是系统如何应对压力。生产系统不仅可以通过快速,可靠的网络传递良好的有效载荷,它还必须处理无效,损坏或仅通过不可靠和不可预测的网络传送的普通缺乏有效载荷。

模拟压力

与ICEI需要支持的有效载荷大小的分布一样,我们还需要考虑生产中通常遇到的错误类型和它们发生的频率。由于遗留的ICEI是一个HTTP API,在处理请求时产生的错误导致响应包含已知的HTTP状态码。旧的ICEI使用了New Relic Java代理,该代理自动记录存储在New Relic数据库(NRDB)。这允许我们编写一个NRQL查询来告诉我们在生产中看到的各种错误代码的相对频率:

错误代码NRQL查询

表格可视化提供了不同状态码的数字计数,但饼图可视化将提供一个图例,其中包括百分比:

错误代码NRQL查询饼图

使用这些数据,我们修改了负载发生器,以在相同频率下诱导这些相同类型的错误,并将它们应用于随机生成的有效负载,这些有效负载符合我们在生产中测量的有效负载大小直方图。为了验证我们的工作,我们向load generator指示板添加了一个饼状图,以显示测试运行期间生成的错误的分类。有了这些数据,我们可以将负载与被测试的系统进行比较,并确定它是否工作正常。

我们构建的加载生成器被部署为Docker容器,允许我们将多个实例并行联机以增加负载。它将负载分散到多个帐户,以迫使被测试的系统响应最广泛的各种条件,并允许团队在初始化测试运行时重新配置错误率和负载大小分布,以实现最大的灵活性。

有了这个工具,我们开始在我们的staging环境中测试系统,以验证它是否正确地响应各种输入,同时也确定新ICEI的一个实例的最大可持续吞吐量。

令人难以置信的增长

我们使用Docker部署新的ICEI我们还需要知道在我们的生产环境中需要多少实例来处理负载。一旦我们知道了一个实例的比例因子,我们就可以计算给定特定内存和CPU限制配置所需的实例总数:

托管要求:

ICEI托管需求表

这种硬件消耗的减少显示了Ratpack由于异步请求处理而带来的效率提高。这也反映了使用我们测量的数据来设计系统的一个好处:显着降低运营成本。此外,切换到Docker意味着扩展以处理不断增加的流量,这仅仅是部署更多容器的问题。遗留的ICEI只能通过在我们的数据中心的机架上添加物理硬件来扩展。

一旦我们知道需要多少实例来托管系统,我们黑暗部署了新的ICEI进入生产。然后我们使用我们的见解仪表板和仪表板对生产系统进行负载和压力测试。新的遗物警报追踪性能和稳定性的政策。一旦测试完成100%成功,我们就知道我们已经建立了一个准备好处理我们的生产负荷的系统。

是部署的时间......

定格。记录。

我不想破坏这个惊喜,但这当然不是那么容易。一旦我们将系统暴露于实际的生产流量中,我们就会发现我们所构建的负载生成器仍然无法模拟真实的情况。在工作完成之前,我们还有很多工作要做。

在里面在下一篇文章在“为规模设计”系列中,我深入研究了在生产中开始canary测试应用程序时遇到的复杂问题。

不要错过“为规模而设计”系列的所有部分:

最近抛弃了这一点的旧学校后端和嵌入式系统工程师为团队驱动,基于Web,现代软件开发的美丽梦想。(但如果你想踢回和谈论微控制器,我在这里为您。)查看帖子

对新遗物博客的写作有兴趣吗?亚搏体育登入网给我们发一份建议书!