如何加载测试并优化API (1)

本文由Donny翻译自3scale.com的《如何加载测试&;优化API的性能》

近年来,API的角色一直在演变。以前API只是作为内部系统之间的集成点,现在API已经成为一个公司的核心系统,一个建立在Web和移动应用之上的核心系统。

当API仅用于处理后台任务(比如生成报告)时,性能几乎不是问题。但是现在API已经逐渐发展成为服务和最终用户之间的核心纽带。这个关键的角色转变说明了一个重要的点:API的性能真的很重要。

如果API数据源响应快,那么前端应用程序的设计就更好,或者几乎可以忽略不计。如果反应慢如蜗牛,那么前端设计就是天然蛋。目前我们客户端应用展示的数据源可能都是多个API响应内容的聚合,对于这种微服务架构来说,性能真的非常重要。

毫不夸张的说,优秀的性能是你的API提供的最好的功能。我们知道,提高目标唯一正确的方法就是找到问题的关键点,或者说关键路径,迭代地度量和调整你的架构系统,直到系统达到预定的目标。对于API来说,衡量和提升性能的过程就是负载和压力测试的过程。

本文将关注如何测试API的负载压力。我们将从一个简单的、未经测试的示例开始,然后添加一个访问控制层,以确保一切都经过严格测试,并准备好处理实际流量。好了,我们开始吧!

首先我们要明确测试什么,可以是你所有的API接口,也可以是单个API接口,也可以是需要排查故障或者改进的API接口的例行测试。

在本文的其余部分,我们将使用一个示例API。这是一个象棋游戏Node.js API。它有三个API接口:

/question–返回随机黑卡。

/answer–返回一张随机的白色卡片。

/pick–返回一对随机问题和答案。

您的测试负载与真实环境越相似,您的负载测试就越有用。如果你不知道实际的流量或者所有接口上的负载是否一致,那么即使你知道你的API可以维持400个请求/秒的吞吐量也是没有用的。

因此,您应该从收集API的使用数据开始。您可以直接从API服务日志或正在使用的其他应用程序性能工具(如New Relic)获取数据。在第一次测试您的API之前,您应该了解以下问题:

(1)每秒请求的平均吞吐量。

(2)峰值吞吐量(某段时间内你得到的最大流量是多少?)(峰值吞吐量)

(3)3)API接口的吞吐量分布(有没有流量远超其他接口的接口?)

(4)用户的吞吐量分布(少数用户产生大部分流量,还是分布更均匀?)

另一个需要考虑的关键点是在测试期间将模拟什么样的流量。主要考虑因素是:

(1)重复性负荷生成

(2)流型模拟

(3)真实流量

通常情况下,我们最好从最简单的方式开始测试,然后逐渐演变成更接近真实环境的测试。我们可以先用重复负载生成作为API接口的第一个测试,这样不仅可以验证我们的测试环境是否稳定,更重要的是让我们找到API可以承受的最大吞吐量,从而知道API的性能上限可以达到什么。

在找到API性能的上限之后,您可以开始考虑如何使您生成的测试流量更接近真实环境。用真实流量来测试比较理想,但实际操作不可行。模拟真实交通既困难又费时。所以我们有一个折中的方法:先研究你的流量分析数据,做一个简单的概率模拟。举个例子,如果你有100个API接口(提示:这里我可以把原来的端点翻译成一个接口,但是翻译成一个接口更好理解),你上个月查了一下使用情况,发现80%的流量来自20个接口,其中3个接口占用了50%的流量。然后,您可以根据这个概率创建一个请求列表,并将其提供给您的负载测试工具。这样就快多了,也比较接近你的真实负载,可以显示出你在实际环境中可能遇到的问题。

最后,如果您获得了想要测试的API的真实访问日志,您可以使用它们来进行最接近客观现实的测试。我们稍后将讨论的大多数负载测试工具都接收一个请求列表作为输入文件。您可以使用您的访问日志,并做一点格式调整,以匹配每个测试工具所需的格式。通过这样做,您可以很容易地在测试环境中重现您的生产流程。

你知道你要测试的是什么。准备的最后一步是配置您的测试环境。你需要一个专用的测试环境。如果你不怕被老板骂,或者你很任性,也可以直接在你的生产环境下进行性能测试,但是不要说有问题我没有提前跟你说清楚。

如果您已经建立了一个预生产或沙盒环境,并且您的API正在其上运行,那么一切都准备好了。因为本文将使用样例API,所以我们将在AWS的服务实例上设置环境。

在我们的例子中,我们使用一个简单的API,不需要从磁盘中读取或者在内存中保存大型数据集。我们选择Linux c4.large的实例就足够了..

注意:我们比较了其他具有相似处理资源但内存更大的AWS实例,但实际测试中没有使用大部分内存,所以我们选择了C4.large。

接下来,我们将运行一个装备良好的负载测试实例(server),它只是一个运行模拟测试程序的服务器,它会从多个并发连接向我们的API服务器重复发送请求。你需要模拟的负载越高,对机器的性能要求就越高。第三,这也是一个CPU密集型工作负载。这里我们选择c4.xlarge AWS服务器,4个虚拟核心,16个ECU优化处理器。

我们选择将所有实例部署在同一个可用区域(API服务器和测试服务器在同一个区域/机房),这样可以将外界因素对我们测试结果的影响降到最低。

我们有一个沙盒环境来运行我们的API,另一个服务器已经准备好开始负载测试。如果这是您的第一次性能测试,您会想知道最好的方法是什么。在本节中,我们将分享我们如何选择工具,并介绍一些市场上普遍接受的工具。

JMeter

在人们的意识中,第一个估计就是Apache JMeter,这是一个开源的Java程序。它的关键特性是为创建测试计划提供一个强大而完美的GUI。测试计划由测试组件组成,测试组件定义了测试的每个部分,例如:

(1)用于注入负载测试的螺纹

(2)参数化测试中使用的HTTP请求

(3)可以添加监听器,可以用不同的方式显示测试结果,就像widget测试组件一样。

优势:

(1)它是功能负载测试的最佳工具。您可以设置条件来模拟复杂的用户流,也可以创建断言来验证行为。

(2)轻松模拟复杂的http请求,如请求前的登录验证或文件上传。

(3)扩展性强,很多社区插件可以修改或扩展内置行为。

(4)开源和免费

缺点:

(1)GUI学习曲线很陡,选项很多。在你运行第一个测试之前,你必须知道很多概念。

(2)测试高负载时,操作步骤很麻烦。您需要先使用GUI工具生成XML测试计划,然后导入测试计划在非GUI模式下运行测试,因为GUI会消耗大量本该用于生成负载的资源。您还需要注意应该禁用或启用哪些监听器(收集数据和显示测量结果的组件),因为它们也消耗资源。测试之后,您需要将原始结果数据导入到GUI中来查看结果。

(3)如果你的目标是测试一段时间内的持续吞吐量(比如60秒内每秒1000个请求),那么很难找到正确的并发线程数和定时器来找到一个相对稳定的值。

JMeter只是我们开始测试时使用的一个工具,我们很快开始寻找其他替代方案。原因是,如果你的目标是在Web应用上对复杂的用户流进行压力测试,那么JMeter可能是最好的工具,但如果你只是需要在一些HTTP API接口上测试性能,那么使用它会杀鸡取卵。

Wrk

Wrk是一个非常类似于传统Apache基准的工具(最初用作Apache服务器的测试工具)。Wrk和ab与JMeter完全不同:

(1)一切都可以通过命令行工具进行配置和执行。

(2)配置少但功能强大,基本生成HTTP负载只需要很少的配置。

(3)性能强劲

但是,与传统的ab工具相比,仍然有几个优点,主要是:

(1)多线程,因此可以利用多核处理器的优势,更容易产生更高的负载。

(2)很容易通过Lua脚本扩展默认行为。

缺点是生成的默认报告内容和格式有限(只有文字,没有图形)。当您的目标是找到您的API可以处理的最大负载时,那么wrk是您最好的选择工具。Wrk可以快速使用。

贝吉塔

贝吉塔是一个开源命令行工具,但它使用的方式与我们之前看到的不同。它关注于如何达到和保持每秒的请求率。也就是说,它侧重于API支持每秒X个请求时的服务行为。当您有实际数据或对您将达到的高峰流量的估计时,这非常有用。你可以用它来验证你的API是否能满足你的需求。

SaaS工具

正如您之前看到的,运行一个简单的负载测试需要准备配置环境。最近,一些产品提供负载测试服务。我们试过两个,Loader.io和Blazemeter(旁白:阿里还有一个性能测试工具PTS,外国人大概没试过)。

注意:我们只试用了这两个工具的免费版本,所以得到的测试结果只适用于免费版本。

火焰测量器

这个产品和前面提到的JMeter有同样的问题:如果你只需要用它进行高负载测试,你需要在GUI界面上创建测试计划,然后在另一个运行非GUI模式的JMeter中导入这些计划。Blazemeter允许你将JMeter的测试计划上传到他们的云端并运行,但遗憾的是免费版只能设置50个并发用户。

Loader.io

它是SendGrid出品的一款简单而强大的云负载测试服务工具。它有你需要的功能和漂亮的视觉报告。Loader.io的免费版还是不错的,吞吐量高达每秒10000个请求,基本可以用它来运行一个真实的负载测试。

我们建议使用多种工具,这样我们可以多次检查我们的测试结果。不同的工具有不同的功能和方法,可以在更多方面反映测试结果。

让我们先试着找到我们的API所能承受的最大吞吐量。在这个吞吐量下,我们的API服务达到了最大的CPU利用率,而没有返回任何错误或超时。这个吞吐量可以作为我们后面测试的每秒请求数。

同样,需要注意的是,CPU是限制因素之一,但你也必须清楚地知道哪些资源会成为你的API的性能瓶颈。

我们有必要在API服务器上安装一些工具,这样我们就可以在测试期间监控资源的利用情况。我们用?Keymetrics.io?然后呢。PM2?模块。

我们的Node.js应用程序运行一个非常简单的HTTP服务。Node.js采用单线程设计,但是为了利用c4.large AWS实例中提供的双核,我们使用PM2的集群功能来运行应用的两个工作进程。

因为我们的API是完全无状态的,所以很容易使用PM2的核心集群模块(内部直接使用PM2)。PM2提供的集群功能提供了一个很好的快捷命令来启动/停止/重新加载应用程序,还可以监控进程。

我们先用Loader.io测试一下API。以下是持续30秒每秒10000次请求的测试结果。10000个请求是Loader.io免费版本中允许的最大吞吐量

在测试过程中,我们观察到API服务器的CPU处理器在测试过程中只有几次达到100%的容量。

这意味着我们的API可以处理更高的吞吐量。然后,我们通过运行wrk进行第二次测试来确认这一点。我们的目标是将API服务器的性能推向极限。

wrk -t 4 -c 1000 -d 60 -延迟-超时3s http://api-server/questions

以下是我们对此测试的重复测试结果:

运行1m测试@ http://api-server/question

4个线程和1000个连接

线程统计平均标准偏差最大值+/-标准偏差

延迟62.23毫秒30.85毫秒1.35秒99.39%

请求/秒4.07千357.61 5.27千94.29%

延迟分布

50% 60.04毫秒

75% 63.85毫秒

90% 64.17毫秒

99% 75.86毫秒

972482请求在1.00m,189.89MB读取

每秒请求数:16206.04

传输速度/秒:3.16MB

结果表明,我们的预感得到了证实:它达到16,206个请求/秒,同时保持合理的延迟,第99百分位只有75.86毫秒。我们将此作为我们的基准最大吞吐量,因为这次我们看到了API服务器的最大容量:

我们刚刚看到了一个简单的方法,找出你的API可以承受的最大流量负载,在这个过程中,我们介绍和讨论了一些我们看到的工具。

请继续关注本文第二部分,我们会介绍如何控制流量,不要让一个随便的客户端轻易越过你的API。我们将展示如何确保我们的API的性能不受在架构前端添加代理的影响。

本文翻译自:如何加载测试& amp;优化API的性能