简体   繁体   English

异步并发速率限制

[英]Asyncio concurrency rate limit

I am new to python and have been trying to set a rate limit for a program that works with asyncio for concurrent requests but after trying almost everything I found in stackoverflow and other programming websites I don't really know if I am missing something or I am doing it wrong so I hope the community can help me.我是 python 新手,一直在尝试为与 asyncio 一起处理并发请求的程序设置速率限制,但是在尝试了我在 stackoverflow 和其他编程网站中找到的几乎所有内容之后,我真的不知道我是否遗漏了什么或者我我做错了,所以我希望社区可以帮助我。

My implementation is pretty straightforward for an asyncio program:对于 asyncio 程序,我的实现非常简单:

async def inside_api_call_1(data, session):
  r = await do_request()
  return r;

async def inside_api_call_2(data, session):
  r = await do_another_request()
  return r;

async def full_process(data, session):
  res1 = await inside_api_call_1(data, session)
  if (res1):
    res2 = await inside_api_call_1(data, session)

async def main_func():
  tasks = []
  async with aiohttp.ClientSession() as session:
    for data in some_json_file:
      tasks.append(full_process(data, session))
    await asyncio.gather(*tasks, return_exceptions=True)

loop = asyncio.get_event_loop()
loop.run_until_complete(main_block())

What I am trying to do is set a rate limit for these _api_call functions to be 16 req/sec GLOBALLY (the sum of all requests (in this case I am making two request one after another as the second needs the first one result to proceed) must not exceed 16 req/sec)我想要做的是将这些 _api_call 函数的速率限制设置为 16 req/sec GLOBALLY(所有请求的总和(在这种情况下,我一个接一个地发出两个请求,因为第二个需要第一个结果才能继续) 不得超过 16 个请求/秒)

My first thought was to set an sleep(1/16) for both functions like this:我的第一个想法是为这两个函数设置一个睡眠(1/16):

async def inside_api_call_1(data, session):
  r = await do_request()
  await asyncio.sleep(1/16) # <--- Wait 1/16 sec
  return r;

async def inside_api_call_2(data, session):
  r = await do_another_request()
  await asyncio.sleep(1/16) # <--- Wait 1/16 sec
  return r;

But it didn't work as I kept getting 429 Too Many Request errors.但它不起作用,因为我不断收到 429 Too Many Request 错误。

Also tried semaphores, but this solution seems to be related more to the number of active connections at the same time rather than the number of req / sec也尝试过信号量,但这个解决方案似乎更多地与同时活动连接的数量有关,而不是与 req / sec 的数量有关

aiohttp: set maximum number of requests per second aiohttp:设置每秒最大请求数

Then I attempted to use the python package https://github.com/hallazzang/asyncio-throttle And set my code like this:然后我尝试使用 python 包https://github.com/hallazzang/asyncio-throttle并将我的代码设置为:

async def main_func():
  tasks = []
  throttler = Throttler(rate_limit=16) <-- setting throttler to 16 req / sec
  async with throttler:
    async with aiohttp.ClientSession() as session:
      for data in some_json_file:
        tasks.append(full_process(data, session))
      await asyncio.gather(*tasks, return_exceptions=True)
  await asyncio.sleep(1/16) <-- This line as the documentation put in the example

loop = asyncio.get_event_loop()
loop.run_until_complete(main_block())

From here I have been moving the statements both for the sleep method and the asyncio-throttle process from the main_func to the inside_api_call methods:从这里我一直将 sleep 方法和 asyncio-throttle 进程的语句从 main_func 移动到 inside_api_call 方法:

async def inside_api_call_1(data, session):
  async with throttler:
    r = await do_request()
    await asyncio.sleep(1/16)
  return r;

async def inside_api_call_2(data, session):
  async with throttler:
    r = await do_another_request()
    await asyncio.sleep(1/16)
  return r;

Without success.没有成功。

I am also new to async in Python so any help is appreaciated.我对 Python 中的异步也很陌生,因此可以得到任何帮助。

Try https://pypi.org/project/limiter/ or尝试https://pypi.org/project/limiter/

    async def main_func():
        tasks = []
        async with aiohttp.ClientSession() as session:
            for idx, data in enumerate(some_json_file):
                tasks.append(full_process(data, session))
                if idx % 16 == 0:
                    await asyncio.gather(*tasks, return_exceptions=True)
                    tasks = []
                    sleep(1)
            if tasks:
                await asyncio.gather(*tasks, return_exceptions=True)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM