Основанный на Memcache алгоритм ограничения скорости? (Токен ведро?) - PullRequest
5 голосов
/ 06 сентября 2010

Я ищу эффективный подход к запросу ограничения скорости от Google App Engine к стороннему сервису. Сторонний тариф на обслуживание ограничивает количество запросов для каждой учетной записи, а на стороне Google App Engine большая часть работы выполняется внутри задач. Сегменты токенов - это отличный общий алгоритм.

В: какой подход может быть использован для эффективного ограничения запросов по отдельным аккаунтам, а не по сервисам?

Это не должно включать настройку ставок в очередях задач GAE, поскольку количество запросов на одну учетную запись и количество обслуживаемых учетных записей будет сильно различаться. Из соображений производительности меня больше всего интересуют идеи на основе memcache (incr / decr?)!

Я думаю, это сводится к ведению токенов на основе memcache?

Мысли

Ответы [ 3 ]

1 голос
/ 31 января 2014

Я знаю, что это старый вопрос, но это лучший результат поиска, и я подумал, что другие могут найти альтернативу, которую я сделал полезной. Это немного более детально (с точностью до секунды), просто (только одна функция) и производительность (только один поиск в 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!')
1 голос
/ 09 февраля 2016

Вот как я реализовал контейнер токенов с memcache на GAE:

Редактировать: взять (еще один) удар в этом.

Это частично позаимствовано у 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 False
1 голос
/ 06 сентября 2010

Я недавно оставил этот проект в качестве закладки: http://code.google.com/p/gaedjango-ratelimitcache/

Не совсем ответ на ваш конкретный вопрос, но, возможно, он поможет вам начать работу.

...