我有一个关于如何减慢api请求的问题。对于特定的第三方API,我打击允许我每2秒发出3个请求。如果我查看该号码,我将返回status code 429
以及等待时间(以毫秒为单位)。
此api经常被调用,并且是我自己的服务器具有不受速率限制的传入请求的直接结果。
由于我不需要同步处理第三方api请求,因此我决定将工作卸载到AWS上的弹性beanstalk工作箱,默认情况下从Amazon SQS读取。
结果,如果从第三方api返回状态代码429,我的工作人员将把SQS消息抛回队列。当等待时间到达时,这不可避免地使api调用工作。然而,这似乎是一个糟糕的解决方案
有没有办法告诉工作盒上的守护进程将消息留在队列中分配的等待时间?或者我可以设置守护程序从队列中读取的速率吗?我正在寻找一种正确的方法(特定于实现)来使用AWS上的worker和队列来限制速率。非常感谢你的帮助!
编辑: 我会假设有一些配置可以在AWS上进行修改以实现我的要求,但无论哪种方式我都在为我所描述的设置寻找特定的解决方案。我不太确定如何修改或控制弹性beanstalk工作盒上的守护进程。
答案 0 :(得分:1)
据我了解,您有大量触发器可用于呼叫第三方服务,您需要对API调用进行速率限制。
最好的方法是对从SQS读取的守护进程进行速率限制。根据编写守护程序的语言,您应该能够轻松找到可以重用的速率限制库。例如,Java和Python分别拥有经过良好测试的库here和here。
请记住,这些库每个工作者每秒允许X个请求。如果你有一个守护进程在运行,那么对于你的用例,X将是1.5。如果你有两个守护进程(例如,两个不同的机器上都有一个守护进程),X应该是0.75
答案 1 :(得分:1)
听起来您从SQS队列中获取了一条消息,在处理该消息时,您发现现在无法完成处理,并且您希望在将来的某个已知时间之后推迟重试。
如果是这种情况,那么您可能希望查看changing the message visibility时间。
当您从队列中读取消息时,它不会自动删除。相反,如果您不在可见性超时内删除消息,它将自动再次发送。我们的想法是确保在删除所有消息之前重试所有消息,但在消费者有机会处理和删除消息之前不要重试。该队列具有默认的可见性超时,您可以基于每个消息覆盖该超时。
请注意,此方法仅使您在超时之前不会从队列中收到特定消息。如果您的客户端进程继续尝试读取消息,它将同时接收其他消息。如果存在与不同消息相关联的不同速率限制,则可能是您想要的。但是,如果没有,您可能希望让客户端线程休眠,直到达到速率限制等待时间。有关如何使多个服务器上的多个线程停止工作直到设定的时间点与AWS无关并且对您正在使用的语言高度特定的详细信息。如果你决定走这条路,你可能应该问一个单独的问题。
答案 2 :(得分:1)
我通常使用的一种模式是在命令中拖延调度下一个作业。因此,当一项工作完成工作时,它会在末尾递归调用下一个,这与第三方API速率限制的标头或超时中的速率限制检查相结合很有用。根据状态的性质,您可以在数据库中查找下一个状态,也可以从数组中弹出一个ID号。
此模式确实有一些警告,首先是,如果您没有实现它,则必须重构代码,其次,您可能需要cron来进行健全性检查或“准备”第一项工作。 / p>
到目前为止,这种模式对我来说效果很好,但是我的用户行为已经改变,并且有各种各样的请求(具有不同类型的作业)可以随时排队,因此这些作业需要了解其他作业影响速率限制。这意味着将某种原子计数放入高速缓存中,以便它们都读取以确定是否是执行或重新调度自身以供以后使用的好时机。或者,仍然执行,捕获429错误,然后重新分配自身,以供稍后延迟。两者都觉得有点脏。
针对此确切用例的内置SQS解决方案将非常简洁。