赢得自定义新的遗物弹球机!只需将数据书呆子提交以注册Futureestack。 现在注册

新的遗物限制API过载 - 也可以,也可以!

11分钟阅读

API是一种越来越受欢迎的业务方式,可以与客户和合作伙伴互动,而无需为每个交互构建特定功能。然而,随着越来越多的客户利用这些API,公司正在被迫与如何适当限制API使用以防止有意或无意的过载。

这篇文章介绍了New Relic内部处理这个问题的一些方法,并深入探讨了我们如何处理一个特别令人困惑的API使用问题。我们希望它能帮助您了解如何在自己的商店中处理API的过度使用。(是的,它很长,但是有图片!你至少应该看看照片!)

新遗物的API方法

我们最初介绍了新的遗物REST API帮助我们的客户直接从我们的产品访问数据。亚博最新版直播从那时起,我们在保护自己免受所有api过载方面取得了很大进展。

具体而言,我们开发了许多技术来限制资源使用,并减轻API重载的效果(请注意,这里讨论的技术不适用于我们通过客户收到数据的摄取管道)。

例如,我们将硬件池分开了新遗物APM来自其UI的API。APM使用这一点独角兽Web服务器,它产生许多工作进程,每个工作进程一次只能处理一个请求。这种简单的“每个进程一次一个请求”并发模型并不新颖,但它是经过验证的,并提供了一些重要的好处,包括强大的故障隔离(一个工作进程中的故障或崩溃保证只局限于该进程)。

独角兽完全单螺纹;单个过程从套接字中提取请求,生成响应,将其写回套接字,然后等待下一个请求到达。所以,能够处理N请求同时请求,我们需要至少运行N独角兽工人流程。

我们使用静态文件而不捆绑独角兽工作nginx.作为一个反向代理在独角兽面前。所以正常的请求流程是这样的:

请求流程图

用这种方法,t阻止API用户消耗所有可用工作时间的具体原因是,API请求由专用的硬件资源池提供服务,这意味着我们总是为UI请求保留容量。

当然,没有一种系统是万无一失的,所以让我们重新关注API/UI工作池的分离。尽管分离了API和UI流量,但大量API用户仍然可以通过影响共享的下游依赖关系来破坏UI。下面是单个API请求的稍微扩展版:

请求流程图

API主机和UI主机都依赖于我们的公制TimeLICE服务,它提供对所有新遗物产品的消费量程的访问权限(MTS也有自己的技术来防止过载)。亚博最新版直播这意味着如果单个API用户可以通过API发送足够昂贵的MTS查询,它可能会影响MTS,因此所有MTS的消费者,包括APM的UI。

这就是我们创造的原因API过载保护

这是我们构建的内部资源限制工具,以跟踪每个API键使用的Unicorn Worker时间。如果该时间变得过多,则该工具将自动限制该API键一段时间。

我们设计了API过载保护,以便在无需控制访问的应用程序的合作,以防范应用程序的故障。这意味着它最终得到了nginx的定时测量。

粗略的序列是这样的:

  1. 客户要求到达Nginx。
  2. 一些Lua运行在nginx进程中的代码(称为“bouncer”)咨询Redis数据库,看看与请求相关的API键是否超过了它的工作时间预算。如果是,则终止请求;如果不是,它会继续。
  3. Nginx将请求传递给Unicorn,后者生成一个响应并返回。
  4. nginx注意了unicorn(称为“nginx Parlance中的”上游“服务器的时间量)采取了响应并通过发送特殊格式化来记录它UDP.数据包到API过载保护工具。
  5. nginx将响应发送回客户端。
  6. 在某些时候,该工具更新其内部计数器,该计数器跟踪API键所消耗的工作时间的总量。

以下是所有这些在图表中看起来的样子:

请求流程图

调查我们案卷上的一个谜团

这种方法在New Relic上运行得很好,使我们能够满足客户的需求,并改善我们的整体API使用。但边缘案例仍然不可避免地会引发问题。虽然每个案例都不一样,但我们希望分享一个内部调查,希望它可以帮助其他公司追踪他们自己的API超载问题。

在调查最近的一个案例时,似乎API过载保护应该为客户切断API访问,但没有,我们注意到一个奇怪的差异:新的遗物见解新遗物APM API的事务数据表明,在被阻止之前,客户已使用远远超过其分配。在一个特定的一小时期间的差异是STARK:该工具认为API键只使用了合理的独角兽工作时间,但洞察交易数据表明总数很长,更长时间!如果该工具已准确了解API键的使用情况,则它将能够减少影响的持续时间超过700% !

因为我们在过去事件中看到了类似的差异,我们决定调查。

面对见解交易数据和工具内部会计之间的差异,我们寻找一个绑架:nginx访问日志。在我们的nginx访问日志中,我们录制了关于每个请求的多个相关属性:

  • 面向客户端的响应时间(NGINX第一次看到请求的经过时间,并且当它写对客户端时的响应)
  • 面向客户端的响应代码(例如,200,404)
  • 上游响应时间(nginx等待Unicorn返回响应的时间)
  • 上游响应代码(Unicorn交给Nginx的响应代码)

使用一些跨越启发式,例如检查请求时间戳和URL,我们能够将从一个特定主机的Nginx访问日志与从洞察力导出的相应事务事件匹配请求记录。

然后,我们生成了一个散点图,显示面向客户端的响应时间和我们自己的Ruby代理从Unicorn流程中报告的响应时间之间的关系。

散点图
散点图

注意什么奇怪?

面向客户端(nginx)和上游(Unicorn)响应时间应该紧密相关。nginx为任何给定的请求的大多数“工作”正在等待Unicorn返回响应。这种紧张的相关性适用于0到5秒的要求,但该图显示了左右4.67秒的不同“膝关节”。这是第一个在Nginx中对响应时间数据有所了解的第一个线索(因此在API过载保护工具中)。

当我们在NGINX访问日志中审视了与客户端响应时间为4到5秒的请求时,我们发现了一个明确的模式。他们中的许多看起来如此:

05/2月/ 2017年2月06日:06:49:02 -0800 || 404 | 4.668 |  -  |  -  |  -  | 127.0.0.1:8100 | 287 | 0 |  -  |获取| HTTPS | / 6/Applications/33591900/metrics.json |-  | api.newrelic.com | Newrelic出口商

上面显示的电子表格行中的第三项和第四项是面向客户端的响应代码和响应时间。第五和第六项是上游响应代码和响应时间。有几件奇怪的事情:

  1. 此请求不应生成404响应。URL是正确的,并导致真正的应用程序。
  2. 洞察中相应的交易事件报告的持续时间几乎为30秒,大于由nginx作为客户端的响应时间报告的4.668秒。
  3. nginx列出了上游响应代码和上游响应时间,如“ - ”,表明它尚未在它写出此日志行时收到Unicorn的响应。

建立一个辩护案

现在回想起来,这些集合起来的线索应该足以告诉我们发生了什么,但我们仍然摸不着头脑。

我们花了几个小时试图拼凑一个重现案例,并追踪与深奥的Linux内核网络设置有关的死胡同。最直接的解释是nginx在Unicorn通过本地套接字写回一个响应之前放弃了等待Unicorn的时间,但这并没有得到证据的支持。Nginx被配置为等待Unicorn生成响应的时间超过5秒,经验测试证实,New Relic的APM API请求超过5秒通常不会出现同样的症状。

无奈之下,我们使用Linux的tail和awk命令来查看nginx访问日志,以了解匹配此模式的请求。我们希望能够捕获一个实时的,这样我们就可以捕获loopback接口的数据包跟踪,以便更好地理解nginx和Unicorn之间的通信通道上发生了什么。

幸运的是,这产生了一个意想不到的线索。这种症状很少出现,但似乎主要影响用户代理被列为某种移动设备的请求。

移动设备有什么唯一的唯一?

移动设备通常具有比桌面更多的Spottier网络连接。这意味着由于客户端和nginx之间的链接缓慢,它们更有可能击中网络超时。可能与我们的问题有关吗?

从原始事件中回顾访问日志线,我们看到100%列出了一个“新遗物出口商”的用户代理商。在GitHub上搜索该字符串,我们找到了用于公开可用工具的源代码,用于将数据从新遗物导出到另一个存储系统中。检查来源,我们看到它对新遗物API的出站请求具有5秒的客户端超时。

答对了!用膝盖在上面指出的响应时间图中缠绕在一起。

客户设置自己的超时时会发生什么?

武装了这个问题,即该问题可能是由客户设置请求超时而导致的,我们能够通过卷曲长时间运行的请求端点来轻松尝试测试,然后在返回之前ctrl-c-ing卷曲。nginx访问日志同时。

以下是显示此方案中的事件序列的图表:

请求流程图

简而言之:当客户端关闭连接时,nginx放弃了,从而触发了早期将响应持续时间写入API过载保护工具的Lua代码,而Unicorn仍在繁忙处理请求。由于API过载保护工具的Lua代码中的另一个错误,因此在此方案中报告的响应时间是默认的句点而不是迄今为止所经过的时间。

这个问题不成比例地影响了长期运行的请求,因为这些请求更有可能达到客户端的超时。

等等,那为什么是404呢?

在此方案中,404错误代码有点奇怪选择要报告的响应代码。事实证明,nginx实际上有自己的特殊非标准响应代码:499(客户端关闭连接)。那么,为什么我们在访问日志而不是499s中看到404s?

这看起来是nginx处理事后配置文件指令(我们在请求完成后使用它来运行Lua代码)和客户端断开连接的一个怪癖。

我们怎样才能解决它?

这个问题有几种可能的解决方案,但是我们选择在APM的A亚博直播平台PI服务器使用的nginx配置文件中设置proxy_ignore_client_abort设置。

此设置指示nginx推迟与请求相关联的后处理工作,直到上游服务器(我们的案例中的Unicorn)实际发送了响应,而不是在客户端放弃并关闭连接时立即执行它。

即使客户端设置激进超时值,这将确保API过载保护工具获得更准确的计算每个帐户所消耗的工作时间数量。

希望这次关于New Relic限制API重载方法的讨论能够帮助你建立或更新自己的进程来处理这个问题。尽管这种特殊的边缘情况调查可能不能直接适用于你自己的情况,但我们希望我们用来识别和纠正情况的过程将有助于为解决你自己的问题指明一条道路。

有一件事是肯定的:API的崛起将继续,因此发现限制过载的方法可能会随着时间的推移成为一个更重要的问题。