Как справиться с ограничением скорости при помощи request_futures? - PullRequest
0 голосов
/ 06 октября 2019

Я использую Python-запросы для получения данных от API, но я хочу ускорить их, выполняя асинхронный запуск с request_futures. Мне разрешено только 200 запросов API в минуту, поэтому я должен проверить это и подождать указанное количество секунд, прежде чем повторить попытку. Этот номер возвращается в заголовке Retry-After. Вот оригинальный рабочий код:

  session = requests.Session()
  for id in ticketIds:
    url = 'https://colorfront.zendesk.com/api/v2/tickets/' + str(id) + '/comments.json'
    req = requests.get(url, auth=zd_secret)

    if req.status_code == 429:
      time.sleep(int(req.headers['Retry-After']))
      req = requests.get(url, auth=zd_secret)

    comments += req.json()['comments']

Следующий асинхронный код работает до тех пор, пока не достигнет ограничения скорости, тогда все запросы после этого завершатся неудачей.

session = FuturesSession()
  futures = {}
  for id in ticketIds:
    url = 'https://colorfront.zendesk.com/api/v2/tickets/' + str(id) + '/comments.json'
    futures[id] = session.get(url, auth=zd_secret)

  for id in ticketIds:
    comments += futures[id].result().json()['comments']

Когда я достигну скоростипредел, мне нужен способ повторить только запросы, которые не удалось. Есть ли в request_futures какой-то встроенный способ справиться с этим?

Обновление : в библиотекеques_futures нет ничего встроенного для этого. Я обнаружил эту связанную открытую проблему: https://github.com/ross/requests-futures/issues/26. Я попытаюсь ускорить выполнение запросов, так как знаю предел API, но это не поможет, если другой пользователь из моей организации одновременно использует тот же API.

Ответы [ 2 ]

0 голосов
/ 07 октября 2019

Я думаю, что нашел решение. Я не знаю, является ли это лучшим способом, но это избегает другой зависимости. Я могу играть с одновременными запросами max_workers и x, чтобы оптимизировать эффективность в зависимости от скорости интернета в этой кофейне.

session = FuturesSession(max_workers=2)
futures = {}
res = {}
delay = 0
x = 200
while ticketIds:
  time.sleep(delay)
  if len(ticketIds) > x - 1:
    for id in ticketIds[:x]:
      url = 'https://colorfront.zendesk.com/api/v2/tickets/' + str(id) + '/comments.json'
      futures[id] = session.get(url, auth=zd_secret)
  else:
    for id in ticketIds:
      url = 'https://colorfront.zendesk.com/api/v2/tickets/' + str(id) + '/comments.json'
      futures[id] = session.get(url, auth=zd_secret)

  # use a copy of the list
  for id in ticketIds[:]:
    if id in futures:
      res[id] = futures[id].result()
      # remove successful IDs from list
      if res[id].status_code == 200:
        ticketIds.remove(id)
        comments += res[id].json()['comments']
      else:
        delay = int(res[id].headers['Retry-After'])
0 голосов
/ 06 октября 2019

Вы должны иметь возможность использовать модуль Retry из urllib3.util.retry для достижения этого:

from requests_futures.sessions import FuturesSession
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

session = FuturesSession()
retries = 5
status_forcelist = [429]
retry = Retry(
     total=retries,
     read=retries,
     connect=retries,
     respect_retry_after_header=True,
     status_forcelist=status_forcelist,
)

adapter = HTTPAdapter(max_retries=retry)
session.mount('http://', adapter)
session.mount('https://', adapter)

futures = {}
for id in ticketIds:
    url = 'https://colorfront.zendesk.com/api/v2/tickets/' + str(id) + '/comments.json'
    futures[id] = session.get(url, auth=zd_secret)

for id in ticketIds:
    comments += futures[id].result().json()['comments']
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...