如何处理速率限制请求的api?

时间:2018-02-27 17:07:34

标签: node.js architecture api-design throttling

对于小型应用,他们没问题。

但对于有流量的应用,您可以轻松达到限制。

Http协议是req-res驱动的。仅仅因为你的后端遇到限制,你就无法等到发送回应,直到速率限制允许你继续进行api通话。

你做什么?

我可以想到几个场景:

等一下:虽然很糟糕,但有时很容易解决,因为你不需要做任何事情。

排队:这很多工作都反对拨打api电话。这要求首先将其存储在数据库中,然后让后台任务通过数据库并执行任务。用户也会被告知"它正在处理"不是"它完成了"

使用很多api :非常hacky ......管理很多麻烦。假设您正在使用亚马逊,现在您必须创建,验证,验证10个帐户。甚至不可能在您需要用域名验证的地方。因为亚马逊会知道账户abc已经拥有它。

3 个答案:

答案 0 :(得分:1)

扩展您的排队选项:

除非你能够设计出在@Hammerbot完成后达不到这个速率限制的问题,否则我会选择一些队列实现。根据您所面临的负载以及您正在处理的速率限制API,该解决方案可以在复杂性和稳健性方面进行扩展。

<强>推荐

你使用一些图书馆来照顾你。 Node-rate-limiter看起来很有希望。看起来您仍然不得不担心如何处理用户交互(让他们等待,写入db / cache-service并稍后通知他们)。

“最简单的情况” - 不推荐

您可以实现功能最低的队列,并使用数据库或缓存进行备份。我以前做过这个,最初很好。请记住,您将需要实现自己的重试逻辑,将不得不担心像queue starvation **这样的事情。基本上,滚动你自己的注意事项&lt;插入某人已经担心的实施&gt;应该加以考虑。

**(例如,您的呼叫由于某种原因而一直失败,并且突然您的后台进程无休止地重试大量失败的队列工作元素,并且您的应用程序内存不足。)

复杂案例:

您有一堆API调用都受到速率限制,而且这些调用都是在卷上进行的,这些卷会让您开始考虑解耦您的架构,以便面向用户的应用程序不必担心处理此异步背景处理

高级架构:

面向用户的服务器将不同类型的工作单元推送到不同的队列。这些队列中的每一个对应于不同速率限制的处理(例如,每小时10次查询,每天1000次查询)。然后,您有一个“速率限制服务”,作为从不同队列中消耗工作单元的大门。当且仅当速率限制服务表明他们可以时,水平分布的工作人员才会消耗队列中的项目。然后可以将这些工作者的结果写入数据库,然后您可以进行一些后台处理,然后通知您的用户您必须执行的异步工作的结果。

当然,在这种情况下,你正在涉足整个基础设施问题。

为了进一步阅读,您可以使用Lyft's rate-limiting service(我认为实现token bucket algorithm来处理速率限制)。您可以使用Amazon's simple queueing service作为队列,使用Amazon lambda作为队列使用者。

答案 1 :(得分:0)

我认为这取决于您要调用哪个API以及哪些数据。

例如,Facebook将其API调用限制为每小时和每个用户200个请求。因此,如果您的应用增长,并且您正确使用其OAuth实施,则不应限制此处。

现在,您需要什么数据?你真的需要打这些电话吗?您在任何服务器上调用的信息是否可存储?

让我们假设您需要在网站上显示Instagram Feed。因此,在每次访问者请求时,您都会到达Instagram以获取所需的图片。当您的应用增长时,您会达到API限制,因为您拥有的访问者数量超过Instagram API允许的数量。在这种情况下,您绝对应该每小时在服务器上存储一次数据,并让您的用户访问您的数据库,而不是Instagram的数据库。

现在假设您需要在每个请求中为每个用户提供特定信息。是否可以让该用户处理他的连接到API?要么实施API的OAuth 2流程,要么向用户询问他们的API信息(我认为不是很安全......)?

最后,如果您真的无法改变现在的工作方式,我没有看到您在此列出的其他选项。

编辑:最后,正如@Eric Stein在他的评论中所述,一些API允许你通过支付(许多SaaS这样做)来提高你的API限制,所以如果你的应用程序增长,你应该支付那些费用服务(他们为您提供价值,向他们付款是公平的)

答案 2 :(得分:0)

速率限制可能导致您出现问题的原因有两个。

  1. 慢性:(即持续的情况)。您正在达到速率限制,因为您的持续需求超出了您的限额。 在这种情况下,请考虑使用本地缓存,这样您就不会两次要求相同的请求。希望您使用的API具有可靠的“最后修改”日期,以便您可以检测缓存何时过时。通过这种方法,您的API调用将刷新您的缓存,然后您将请求从缓存中提供。

如果这无济于事,则需要更高的速率限制

  1. 急性:您的应用发出的突发呼叫超出了速率限制,但平均而言,您的需求低于该限制。所以你有一个短期的问题。我已经为此解决了一个蛮力的解决方案(“先射击,再询问权限”)。我爆裂直到达到速率限制,然后使用重试逻辑,因为我喜欢的工具python很容易,所以重试逻辑很容易。返回的错误被捕获,重试处理将接管。我认为每个成熟的图书馆都会有这样的东西。

    https://urllib3.readthedocs.io/en/latest/reference/urllib3.util.html

默认重试逻辑是在越来越大的时间内逐步退出。 我认为这有饥饿的风险。也就是说,如果有多个客户端使用相同的API,则它们共享与池相同的速率限制。在您的第n次重试中,您的退避时间可能太长,以至于退避时间较短的新客户端正在窃取您的插槽...当您的长退避时间到期时,速率限制已被年轻的竞争者所占用,因此您现在可以重试甚至更长的时间,使问题变得更糟。解决方案是提供一种不太幼稚的算法,这与您在计算机科学中所做的锁定问题相同(引入随机化是一个很大的改进)。