我正在寻找一种有效的方法来限制从Google App Engine到第三方服务的速率限制请求。第三方服务率限制了每个帐户的请求,而在Google App Engine方面,大多数工作都是在任务内部执行的。令牌桶在这里是一个很好的通用算法。
问:可以使用什么方法有效地限制每个帐户而不是每个服务的请求速率?
这不应该涉及设置GAE任务队列的速率,因为每个帐户的请求数量和服务的帐户数量将有很大差异。出于性能原因,我最感兴趣的是基于memcache的(incr/decr?)点子!
我认为这可以归结为基于memcache的令牌桶?
有什么想法?
发布于 2010-09-07 02:48:53
不久前,我将这个项目保存为书签:http://code.google.com/p/gaedjango-ratelimitcache/
对你的具体问题不是一个真正的答案,但也许它可以帮助你开始。
发布于 2014-01-31 05:28:17
我知道这是一个老生常谈的问题,但这是一个排名靠前的搜索结果,我想其他人可能会找到我做的有用的替代方案。它比上面的解决方案更细粒度(一直到第二个)、简单(只有一个函数)和性能(只有一次memcache查找):
import webapp2
from functools import wraps
from google.appengine.api import memcache
def rate_limit(seconds_per_request=1):
def rate_limiter(function):
@wraps(function)
def wrapper(self, *args, **kwargs):
added = memcache.add('%s:%s' % (self.__class__.__name__, self.request.remote_addr or ''), 1,
time=seconds_per_request, namespace='rate_limiting')
if not added:
self.response.write('Rate limit exceeded.')
self.response.set_status(429)
return
return function(self, *args, **kwargs)
return wrapper
return rate_limiter
class ExampleHandler(webapp2.RequestHandler):
@rate_limit(seconds_per_request=2)
def get(self):
self.response.write('Hello, webapp2!')发布于 2016-02-10 02:56:29
下面是我如何在GAE上使用memcache实现令牌存储桶:
编辑:对此进行(另一个)尝试。
这部分是从https://github.com/simonw/ratelimitcache/blob/master/ratelimitcache.py借用的
def throttle(key, rate_count, rate_seconds, tries=3):
'''
returns True if throttled (not enough tokens available) else False
implements token bucket algorithm
'''
client = memcache.Client(CLIENT_ARGS)
for _ in range(tries):
now = int(time.time())
keys = ['%s-%s' % (key, str(now-i)) for i in range(rate_seconds)]
client.add(keys[0], 0, time=rate_seconds+1)
tokens = client.get_multi(keys[1:])
tokens[keys[0]] = client.gets(keys[0])
if sum(tokens.values()) >= rate_count:
return True
if client.cas(keys[0], tokens[keys[0]] + 1, time=rate_seconds+1) != 0:
return False
logging.error('cache contention error')
return True以下是使用示例:
def test_that_it_throttles_too_many_requests(self):
burst = 1
interval = 1
assert shared.rate_limit.throttle('test', burst, interval) is False
assert shared.rate_limit.throttle('test', burst, interval) is True
def test_that_it_doesnt_throttle_burst_of_requests(self):
burst = 16
interval = 1
for i in range(burst):
assert shared.rate_limit.throttle('test', burst, interval) is False
time.sleep(interval + 1) # memcache has 1 second granularity
for i in range(burst):
assert shared.rate_limit.throttle('test', burst, interval) is Falsehttps://stackoverflow.com/questions/3647949
复制相似问题