我正在开发一个与Web服务API接口的Python库。像我遇到的许多Web服务一样,这个库要求限制请求的速率。我想为类示例化提供一个可选参数limit
,如果提供了这个参数,它将保留传出的请求,直到指定的秒数过去。
据我所知,一般情况如下:类的一个示例通过一个方法发出一个请求。当它发出请求时,该方法发出一些信号,在某处设置一个锁变量,并在limit
中开始一个秒数的倒计时计时器。(很可能,锁就是倒计时器本身。)如果在此时间段内发出另一个请求,则必须将其排队,直到倒计时器达到零,锁被解除;在这一点上,发送队列中最早的请求,并且重置倒计时定时器,并且重新使用锁。
这是线程化的一个例子吗?还有其他我没有看到的方法吗?
倒计时计时器和锁定应该是执行严修变数,还是应该属于类别,让类别的所有执行严修都保留要求?
此外,在库中提供速率限制功能通常是个坏主意吗?我的理由是,由于在默认情况下倒计时是零秒,库仍然允许开发人员使用库并提供他们自己的速率限制方案。然而,假定任何使用该服务的开发人员无论如何都需要对请求进行速率限制,我认为图书馆提供一种限速的手段会很方便。
无论是否在库中放置速率限制方案,我都希望使用该库编写应用程序,因此建议的技术将派上用场。
6条答案
按热度按时间svujldwt1#
除非有必要,否则不要重复发明轮子。检查一下ratelimit库。如果你只是出于某种原因想限制你对rest api的调用,然后继续你的生活,那么它是完美的。
如果发出的请求数超过每分钟一个,这将“阻塞"线程。
vdzxcuhz2#
使用队列和调度程序时效果更好。
您将处理分为两部分:source和dispatch。它们可以是单独的线程(或者是单独的进程,如果更容易的话)。
Source端以任何让它们满意的速率创建请求并将其入队。
调度端执行此操作。
1.获取请求开始时间 s。
1.将请求出列,通过远程服务处理请求。
1.获取当前时间 t。休眠 rate -(t - s)秒。
如果你想运行直接连接到远程服务的Source端,你可以这样做,并绕过速率限制。这对于使用远程服务的模拟版本进行内部测试是很好的。
困难的部分是为每个可以排队的请求创建一些表示,因为Python Queue可以处理几乎所有的事情,所以你不需要做太多。
如果使用多处理,则必须对对象进行pickle操作,才能将它们放入管道中。
ddrv8njm3#
排队可能过于复杂。一个简单的解决方案是为类提供一个变量,表示上次调用服务的时间。每当调用服务时(!1),请将waitTime设置为
delay - Now + lastcalltime
。delay
应等于请求之间允许的最小时间。如果此数字为正数,在进行调用(!2)之前休眠那么长时间。这种方法的缺点/优点是它将Web服务请求视为同步的。优点是它非常简单并且易于实现。当然,S.Lott的解决方案更为优雅。
u4dcyp6a4#
您的速率限制方案应该受到底层代码的调用约定(同步或异步)以及此速率限制将在什么范围(线程、进程、计算机、集群?)内操作的严重影响。
我建议将所有变量都保留在示例中,这样您就可以轻松地实现多个周期/比率的控制。
最后,听起来你想成为一个中间件组件。不要试图成为一个应用程序,自己引入线程。如果你是同步的,就阻塞/休眠,如果你被其中一个调用,就使用异步调度框架。
az31mfrm5#
如果您的库被设计为同步的,那么我建议忽略限制的实施(尽管您可以跟踪速率并至少帮助调用者决定如何荣誉限制)。
现在我使用twisted来与几乎所有的东西接口。它通过一个将请求提交与响应处理分离的模型来使这类事情变得容易。如果你不希望你的API用户不得不使用twisted,你至少最好了解他们的延迟执行API。
例如,我有一个twitter接口,它代表xmpp users推送了相当多的请求,我没有速率限制,但我确实必须做一些工作来防止所有请求同时发生。
vfwfrxfs6#
因此,我假设一些简单的东西,如导入时间time.sleep(2)将无法在请求之间等待2秒