我的第一个想法是使用Redis。但是,还有更多很棒的工具,有些甚至更轻巧,因此我的解决方案基于zmq。因此,您不必运行Redis,足以运行小型Python脚本。
让我先回顾您的要求,然后再描述解决方案。
在固定时间内将对某个资源的请求数限制为多个请求。
自动解锁
资源(自动)解锁应在少于1秒的时间内发生。
它应该被分发。我将假设,您的意思是多个消耗某些资源的分布式服务器应该能够使用,并且只拥有一个更衣室服务就可以了(结论中对此有更多的介绍)
时隙可以是一秒钟,更多秒或更短的时间。唯一的限制是Python中时间测量的精度。
如果您的资源具有每秒定义的硬限制,则应使用时隙1.0
在首次请求访问资源时,为下一个时隙设置开始时间并初始化请求计数器。
对于每个请求,请增加请求计数器(针对当前时隙)并允许该请求,除非您在当前时隙中已达到允许的最大请求数。
您使用的服务器可能分布在更多计算机上。要提供对LockerServer的访问,您将使用zmq。
zmqlocker.py:
import time
import zmq
class Locker():
def __init__(self, max_requests=1, in_seconds=1.0):
self.max_requests = max_requests
self.in_seconds = in_seconds
self.requests = 0
Now = time.time()
self.next_slot = Now + in_seconds
def __iter__(self):
return self
def next(self):
Now = time.time()
if Now > self.next_slot:
self.requests = 0
self.next_slot = Now + self.in_seconds
if self.requests < self.max_requests:
self.requests += 1
return "go"
else:
return "sorry"
class LockerServer():
def __init__(self, max_requests=1, in_seconds=1.0, url="tcp://*:7777"):
locker=Locker(max_requests, in_seconds)
cnt = zmq.Context()
sck = cnt.socket(zmq.REP)
sck.bind(url)
while True:
msg = sck.recv()
sck.send(locker.next())
class LockerClient():
def __init__(self, url="tcp://localhost:7777"):
cnt = zmq.Context()
self.sck = cnt.socket(zmq.REQ)
self.sck.connect(url)
def next(self):
self.sck.send("let me go")
return self.sck.recv()
run_server.py:
from zmqlocker import LockerServer
svr = LockerServer(max_requests=5, in_seconds=0.8)
从命令行:
$ python run_server.py
这将在localhost的默认端口7777上开始提供更衣室服务。
run_client.py:
from zmqlocker import LockerClient
import time
locker_cli = LockerClient()
for i in @R_403_1567@(100):
print time.time(), locker_cli.next()
time.sleep(0.1)
从命令行:
$ python run_client.py
您将看到“ go”,“ go”,“ sorry” …打印的答复。
尝试运行更多客户端。
您可以先启动客户端,然后再启动服务器。客户端将阻塞直到服务器启动,然后才能愉快地运行。
另一方面,您可能会发现资源的限制并没有您想象的那么可预测,因此请准备好使用参数来找到适当的平衡,并始终为此做好准备以应对异常情况。
还有一些空间可以优化提供“锁”的功能- 例如,如果储物柜用完了所允许的请求,但是当前时隙已经快要完成了,您可以考虑稍等一下“抱歉”,在不到一秒钟的时间内提供“进入” ”。
通过“分布式”,我们还可以了解多个一起运行的更衣室服务器。这更难做到,但也是可能的。zmq允许非常容易地连接到多个URL,因此客户端可以真正轻松地连接到多个储物柜服务器。有一个问题,如何协调更衣室服务器以不允许对资源的过多请求。zmq允许服务器间通信。一种模型可能是,每个储物柜服务器将在PUB / SUB上发布每个提供的“开始”。所有其他更衣室服务器都将被订阅,并使用每个“去”来增加其本地请求计数器(使用稍微修改的逻辑)。