退避只重试失败的 API 调用而不是所有 API 调用与异步

Backoff to retry only the failing the API call instead of all the API calls with asyncio

我正在使用具有速率限制的 API 提取信息。我正在以异步方式执行此操作,以使用 asyncio 和 aiohttp 加快进程。我以 10 个为一组收集电话,所以我每次都进行 10 个并发调用。如果我收到 429,我会等待 2 分钟,然后重试...对于重试部分,我正在使用退避装饰器。

我的问题是重试是针对 10 次调用执行的,而不仅仅是针对失败的调用...我不确定该怎么做:

@backoff.on_exception(backoff.expo,aiohttp.ClientError,max_tries=20,logger=my_logger)
async def get_symbols(size,position):
    async with aiohttp.ClientSession() as session:
        queries = get_tasks(session,size,position)
        responses = await asyncio.gather(*queries)
        print("gathering responses")
        for response in responses:
            if response.status == 429:
                print(response.headers)
                print("Code 429 received waiting for 2 minutes")
                print(response)
                time.sleep(120)
                raise aiohttp.ClientError()
            else:
                query_data = await response.read()

有没有人有办法只执行失败的调用而不是整个调用?

您的代码中有两个问题。首先是重复的 sleep——您可能不理解 backoff 是如何工作的。它的重点是 1) 尝试,2) 如果出现错误,睡眠会以指数方式增加延迟,3) 为您重试 function/coroutine。其次,是get_symbolsbackoff装饰了,显然是整体重试了

如何改进?

  1. 装饰个性化请求功能
  2. backoff做它的“休眠”工作
  3. aiohttp通过在ClientSession初始化程序
  4. 中设置raise_for_status=True来为非200 HTTP重新提议代码引发它来完成它的工作

它应该如下所示。

@backoff.on_exception(backoff.expo, aiohttp.ClientError, max_tries=20)
async def send_task(client, params):
    async with client.get('https://python.org/', params=params) as resp:
        return await resp.text()
   
def get_tasks(client, size, position):
    for params in get_param_list(size, position)
        yield send_task(client, params)   

async def get_symbols(size,position):
    async with aiohttp.ClientSession(raise_for_status=True) as client:
        tasks = get_tasks(session, size, position)
        responses = await asyncio.gather(*tasks)
        for response in responses:
            print(await response.read())