Как определить, сколько еще запросов может сделать мое приложение, прежде чем оно достигнет ограничения скорости API Twitter?
Мое приложение обычно делает запрос к API Twitter для временной шкалы пользователя (твиты пользователя).
Кроме того, я использую драгоценный камень twitter и настроил клиент Twitter, чтобы мое приложение могло выполнить запрос:
client = Twitter::REST::Client.new do |config|
config.consumer_key = ENV["TWITTER_CONSUMER_KEY"]
config.consumer_secret = ENV["TWITTER_CONSUMER_SECRET"]
config.access_token = ENV["TWITTER_ACCESS_TOKEN"]
config.access_token_secret = ENV["TWITTER_ACCESS_TOKEN_SECRET"]
end
Конечная точка, к которой я обращаюсь - https://api.twitter.com/1.1/statuses/user_timeline.json
- имеет ограничение скорости 900 запросов каждые 15 минут.
Если я правильно понимаю, есть 2 распространенных способа определить, достигло ли мое приложение своего предела скорости, но ни один из них мне не нужен:
Первый подход:
Это функция, которую я написал, которая пытается сделать запрос на твиты пользователя, и если приложение имеет ограничение скорости, оно вызовет исключение.
def get_tweets_from_TwitterAPI(twitter_handle)
tweets = []
begin
tweets = CLIENT.user_timeline(twitter_handle)
rescue Twitter::Error::TooManyRequests => error
raise error
end
return tweets
end
Проблема такого подхода в том, что я хотел бы узнать, сколько еще запросов может безопасно выполнить мое приложение, прежде чем я сделаю запрос к API Twitter. Я боюсь, что при таком подходе мое приложение будет пинговать API Twitter через много времени после того, как оно достигнет ограничения скорости, и это откроет мое приложение для карательных действий со стороны Twitter (например, мое приложение будет занесено в черный список).
Второй подход Второй подход - сделать запрос к этой конечной точке Twitter - https://api.twitter.com/1.1/application/rate_limit_status.json
- который отправляет данные обратно о том, где находится статус приложения для данного ограничения скорости.
Но опять же, у этой конечной точки также есть собственный предел скорости (180 запросов каждые 15 минут), который не очень высок. Мое приложение взорвется за этот предел. В идеальном мире я хотел бы определить текущий статус ограничения скорости моего приложения, прежде чем я сделаю запрос к API вообще. Так что:
def start_tweets_fetch
number_of_requests_in_last_15 minutes = WHERE DO I GET THIS NUMBER FROM??
if number_of_requests_in_last_15 minutes <= 900
get_tweets_from_TwitterAPI(twitter_handle)
end
end
Я представляю, что мне нужно увеличить число, которое я сохранил в своей базе данных, чтобы отслеживать запросы к API. Или есть более простой способ?
2 ответа
Я не могу говорить о драгоценном камне, который вы используете, но способ отследить лимиты ваших запросов без необходимости дополнительного вызова конечной точки rate_limit_status - это изучить X-Rate-Limit-Remaining
заголовки при каждом вызове API. Однако я не знаю, доступны ли эти данные на геме Ruby, который вы используете.
редактировать
Это ответ на вопрос Энди Пайпера, который, я думаю, является самым простым способом отслеживать оставшиеся звонки.
Предполагая, что вы используете этот драгоценный камень Twitter, похоже, что каждый ответ от драгоценного камня будет заполнять
Twitter::RateLimit
объект с информацией из заголовков ограничения скорости, как предложил Энди.Вы должны быть в состоянии получить доступ к этой информации, как это:
tweets = CLIENT.user_timeline(twitter_handle)
remaining_calls = tweets.rate_limit.remaining
Оттуда вы можете сохранить это значение, чтобы проверить его при следующем запросе. Как вы его сохраните и проверите, зависит от вас, но остальная часть моего ответа все еще может быть полезна для этого.
Примечание: я не пробовал этот метод раньше, но я бы попробовал в вашей ситуации одно из первых, если бы не сохранял журналы запросов на постоянной основе.
Одним из способов может быть использование встроенного в Cache API Rails. Это позволит вам хранить любое значение в кеш-хранилище, которое должно быть быстрее и легче, чем база данных.
number_of_requests_in_last_15 = Rails.cache.fetch("twitter_requests", expires_in: 15.minutes) { 0 }
if number_of_requests_in_last_15 minutes <= 900
get_tweets_from_TwitterAPI(twitter_handle)
Rails.cache.increment("twitter_requests")
end
Давайте разберем это
Rails.cache.fetch("twitter_requests", expires_in: 15.minutes) { 0 }
:
-
fetch
метод наRails.cache
будет пытаться получить значение для ключаtwitter_requests
, - Если ключ не существует, он оценивает блок и устанавливает возвращаемое значение в качестве нового значения ключа и возвращает его. В этом случае, если ключ
twitter_requests
не существует, новое значение ключа будет0
, -
expires_in: 15.minutes
опция, переданная методу извлечения, говорит об автоматической очистке этого ключа (twitter_requests
каждые 15 минут
Rails.cache.increment("twitter_requests")
:
- Увеличивает значение в
twitter_requests
ключ на 1.
Заметки
- По умолчанию Rails будет использовать хранилище данных в памяти. Это должно работать без проблем, но любые значения, хранящиеся в кеше, будут сбрасываться каждый раз, когда вы перезапускаете сервер rails.
- Бэкэнд кеша настраивается и может быть изменен на другие популярные системы (например, memcache, redis), но они также должны быть запущены и доступны Rails.
- Возможно, вы захотите увеличить кеш перед вызовом API, чтобы уменьшить вероятность истечения срока действия кеша между моментом его проверки и приращением. Увеличение ключа, который не существует, вернет
nil
,