我的第一个想法是使用Redis。但是,还有更多很棒的工具,有些甚至更轻巧,因此我的解决方案基于zmq。因此,您不必运行Redis,足以运行小型Python脚本。
需求审查让我先回顾您的要求,然后再描述解决方案。
在固定时间内将对某个资源的请求数限制为多个请求。
自动解锁
资源(自动)解锁应在少于1秒的时间内发生。
它应该被分发。我将假设,您的意思是多个消耗某些资源的分布式服务器应该能够使用,并且只拥有一个更衣室服务就可以了(结论中对此有更多的介绍)
时隙可以是一秒钟,更多秒或更短的时间。唯一的限制是Python中时间测量的精度。
如果您的资源具有每秒定义的硬限制,则应使用时隙1.0
监视每个时隙的请求数,直到下一个请求开始在首次请求访问资源时,为下一个时隙设置开始时间并初始化请求计数器。
对于每个请求,请增加请求计数器(针对当前时隙)并允许该请求,除非您在当前时隙中已达到允许的最大请求数。
与REQ / REP一起使用zmq您使用的服务器可能分布在更多计算机上。要提供对LockerServer的访问,您将使用zmq。
样例代码zmqlocker.py:
运行您的服务器:import timeimport zmqclass 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 LockerServersvr = LockerServer(max_requests=5, in_seconds=0.8)
从命令行:
$ python run_server.py
这将在localhost的默认端口7777上开始提供更衣室服务。
运行您的客户run_client.py:
from zmqlocker import LockerClientimport timelocker_cli = LockerClient()for i in xrange(100): print time.time(), locker_cli.next() time.sleep(0.1)
从命令行:
$ python run_client.py
您将看到“ go”,“ go”,“ sorry” …打印的答复。
尝试运行更多客户端。
一点压力测试您可以先启动客户端,然后再启动服务器。客户端将阻塞直到服务器启动,然后才能愉快地运行。
结论- 满足描述的要求
- 请求数量有限
- 无需解锁,它允许在下一个时隙可用时发出更多请求
- 可通过网络或本地套接字使用LockerService。
- 应该可靠,zmq是成熟的解决方案,python代码相当简单
- 它不需要所有参与者之间的时间同步
- 性能会很好
另一方面,您可能会发现资源的限制并没有您想象的那么可预测,因此请准备好使用参数来找到适当的平衡,并始终为此做好准备以应对异常情况。
还有一些空间可以优化提供“锁”的功能-
例如,如果储物柜用完了所允许的请求,但是当前时隙已经快要完成了,您可以考虑稍等一下“抱歉”,在不到一秒钟的时间内提供“进入” ”。
通过“分布式”,我们还可以了解多个一起运行的更衣室服务器。这更难做到,但也是可能的。zmq允许非常容易地连接到多个URL,因此客户端可以真正轻松地连接到多个储物柜服务器。有一个问题,如何协调更衣室服务器以不允许对资源的过多请求。zmq允许服务器间通信。一种模型可能是,每个储物柜服务器将在PUB
/ SUB上发布每个提供的“开始”。所有其他更衣室服务器都将被订阅,并使用每个“去”来增加其本地请求计数器(使用稍微修改的逻辑)。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)