如何对Ably的控制API进行负载测试

262 阅读8分钟

我们最近公布了Ably的Control API,这是一个REST API ,使你能够以编程方式管理Ably的配置。你现在可以使用控制API来配置任何以前只能通过Ably仪表板配置的东西。

Ably平台是围绕着可靠性的四个支柱设计的。性能完整性可靠性可用性。控制API也不例外;它也应该遵守这些规定,我们的开发过程对它进行了测试,以确保可靠地支持多个同时发生的请求。负载测试确定了Control API在任何时候可以支持的并发用户数量,以及它在重负载下的表现。我们利用负载测试的结果来充分配置我们的服务器资源。

什么是负载测试?

负载测试是通过模拟大量的并发用户来衡量一个系统在压力下的表现。测试场景需要逼真,并尽可能地模拟用户行为。

我们可以用请求来敲打Control API,并计算出使其倒下的并发用户的数量。这是一个很好的衡量标准,但最终这并不能告诉我们为什么它会倒下,或者我们能做什么来防止它,因为它只揭示了压力的突破点,即控制API无法应付的负载。

我们要测量的不仅仅是Control API所能支持的并发用户的数量。我们想了解Control API在特定情况下的表现。

例如,如果它受到攻击并处理多个恶意请求,它对有效请求的服务如何?这对响应延迟有什么影响?我们支持的缓存和数据库集群受到什么影响?所有其他的外部资源和服务是否在正常工作?这是否对Ably系统的其他部分产生了不利影响?

在内部,我们对Control API在大负荷下的表现有一些假设(基于对过去使用情况的合理猜测)。然而,我们希望消除任何猜测,并获得实际数据来支持我们的预测,作为这些测试的一部分。

负载测试的工具

我们以前使用过Apache JMeter进行负载测试,尽管使用它需要克服一个学习曲线,但它是我们这个项目的首选。但它并不那么灵活,主要是因为它在很大程度上依赖于冗长的XML配置,而且它是线程绑定的,这可能是非常耗费资源的,它为每一个模拟的用户创建一个新的线程。

另外,随着我们的控制API的发展,我们希望我们的性能测试脚本能与之一起发展。做到这一点的最好方法之一是在Git中对脚本进行改版。虽然你可以把JMeter的配置检查到Git中,但它很啰嗦,而且可读性不强。

我们转而使用Locust,这是一个开源的、可扩展的、分布式的网络服务负载测试框架,它可以接受直接的Python脚本。与JMeter不同,Locust使用绿色线程,需要较少的资源来模拟用户。我们写了一个Python脚本来设置我们的负载测试,我们已经把它添加到我们的代码库中,这样我们就可以在继续扩展我们通过Control API提供的服务时对它进行扩展。

负载测试时如何确定现实的使用模式

一个强大的负载测试策略需要能够尽可能地模拟用户行为。我们确定了以下类型的用户,我们希望他们能够访问Ably的Control API:

  • 典型用户- 这些用户具有有效的访问权限和良好的意图,他们正在负责任地使用API。
  • 强力用户- 这些用户将我们的系统推向了极限,但没有恶意。
  • 不良用户和机器人- 具有有效访问权限但意图不良,不负责任地使用API的用户。我们也将机器人(和其他没有价值的访问,使控制API忙于服务请求的用户)纳入这一类别。

我们的主要目的是继续为典型用户和高级用户提供服务,不受不良用户或机器人的影响。我们做的第一件事是确定我们确定的用户类型的预期行为。

典型/权力用户

  • 获得有效的授权令牌
  • 提出不同类型的请求来管理请求
  • 每一个请求被节制在几秒钟之内

不好的用户

  • 与好用户的步骤相同,但不受限制

恶意软件

  • 一些人通过有效的认证,而另一些人有无效的/胡言乱语的标记
  • 试图提出管理资源的请求

如何配置Locust

一台机器无法模拟我们所需要的用户数量,因此,为了确保我们能够以所需的用户数量运行测试,我们将Locust配置为以分布式模式运行用户集合(称为Swarm)。

Squid game: how we load-tested Ably’s Control API

主节点。这个节点不模拟任何用户本身。它将运行Locust的Web界面,在那里我们可以开始测试并看到实时统计数据。我们使用Locust的`-master`标志,使任何实例在运行命令时表现为这个节点。

**工作者节点。**这些节点模拟我们的用户。为了使一个实例以工人模式运行,我们使用了`-worker`标志。由于你在测试时可以有多个工作节点,我们使用几个来代表我们不同类型的用户

负载测试时如何处理速率限制的问题

当我们开始进行负载测试时,我们遇到的主要问题之一是速率限制问题。为了减缓或阻止攻击,我们限制特定用户/IP的请求。我们最初的测试设置从同一个IP(测试机器)发送所有的请求,当它达到极限时,它被服务器节流/阻止了。虽然这证实了我们可以限制未经授权的坏用户发出过多的请求,但测试失败了,因为我们也阻止了同一IP上的模拟的好用户。

我们需要模拟来自不同IP的流量负载来测量弹性,所以我们使用Squid代理,这是一个缓存和转发的HTTP网络代理,来转发请求。该网络允许你发送无限的并发连接请求。

我们在AWS账户上设置了几个EC2实例,每个实例都运行一个Squid代理。然后,我们把从本地测试机发出的请求转发到AWS上的代理,以确保请求来自不同的IP,就像它们在现实世界中一样。

负载测试时如何管理资源

就其本质而言,在类似生产环境中的负载测试需要为系统提供大量的资源。我们面临一个问题,因为我们最初为管理所有并发的请求而对数据库的配置不足。我们把它提高了,然后密切关注我们的亚马逊EC2使用情况,以监测我们的消耗。

我们注意到,如果负载测试系统失控,我们可能会产生巨大的账单。在配置我们的测试服务器以密切模拟生产后,我们设置了一些警报,以便在我们的用量过高时发出警告,同时还设置了一些指标,以帮助我们更好地衡量和预测现实世界对Control API的使用。

总结

我们能够为我们所期望的并发用户数量运行测试。这使我们对Control API充满信心,并使我们发现了我们的网络服务器和仪表盘系统的数据库的突破点。这次测试也证实了我们选择Puma作为应用网络服务器是正确的选择。

我们现在有了一个更好的想法,即当我们在一般可用性(GA)中发布控制API时,它的性能如何。我们可以在回归测试中使用它,以确保大型的新功能不会因为我们有阈值指标而意外减慢速度。我们可以利用收集到的信息来进一步优化我们的网络架构。

我们发现Locust和Squid是很好的工具,开箱即用。特别是Locust,使用起来非常方便,可扩展性强,很容易准确配置你想测试的内容。纯粹为了灵活地根据你的用例编写你自己的测试,我们推荐它用于Web应用测试。

有用的资源

来自Ably工程的最新信息