【问题标题】:Asyncio aiohttp - parallel requests made per secondAsyncio aiohttp - 每秒发出的并行请求
【发布时间】:2021-10-01 09:51:57
【问题描述】:

我已查看此帖子(但无法回复):aiohttp: rate limiting parallel requests

首先,我要感谢@Sraw 在上述帖子中的cmets!

但是,我怀疑我目前的解决方案是否做得很好:

for convertedJson in allJsons:
   .....
   .....
   tasks.append(asyncio.ensure_future(fetch(env,typeRequest,convertedJson,headers,retries,execution,session)))
   await asyncio.sleep(1/800)

results = await asyncio.gather(*tasks,return_exceptions=True)
await session.close()

在我的 fetch 函数中,我基本上是这样做的:

async def fetch(env,typeRequest,request,headers,retries,execution,session): 
   .....
   .....
   async with session.post(url=VALIDATION_API_ENDPOINT,json=request["body_request"],headers=headers,timeout=None,allow_redirects=False) as response:
      ......
      ......
      jsonF=await response.json()
      return jsonF

问题是我想每秒发出 800 个请求。我做得对吗?我想很明显,我无法知道收到回复需要多长时间。我想知道我是否已经按照这种逻辑执行了这 800 个请求/秒,因为服务器人员告诉我,我实际上正在执行大约 400 个请求/秒(对我来说没有意义)。

谢谢大家! BR,

【问题讨论】:

    标签: python api request python-asyncio aiohttp


    【解决方案1】:

    Asyncio保证最大执行时间,只保证最小执行时间。这段代码:

    for convertedJson in allJsons:
        ...
        tasks.append(asyncio.ensure_future(fetch(env,typeRequest,convertedJson,headers,retries,execution,session)))
        await asyncio.sleep(1/800)
    

    执行以下操作:

    • 迭代convertedJson
    • 附加一个期货对象
    • 睡眠至少 1/800

    当您只延迟 1.25 毫秒 秒时,执行所有其他步骤所花费的时间就开始变得重要了。您的 asyncio 事件循环还有其他要服务的东西(例如实际执行请求),并且它开始显示:您实际上并没有在一秒钟内完成 800 个请求。您甚至可能还没有完成将它们添加到队列中,因为该循环中的步骤需要一段时间。你肯定没有完成所有的执行(如你所见)。

    总结如下:

    • 你的其他事件不是原子的,所以即使你只睡了 1.25 毫秒,如果它们花费的时间太长,你也会开始遇到问题(因为你不会在 1 秒内完成 800 次循环迭代)。
    • asyncio 的 1.25 毫秒是尽最大努力,但允许更长。它可能就在这里。

    怎么办? 800 个请求/秒显然与您当前的设置相当困难。您可能希望从请求代码中拆分生成这些请求,并在一个专用于执行获取的线程中运行 asyncio 事件循环。您可能想尝试信号量解决方案,它可能(猜测)具有较低的开销。您可能希望让更多代码等待(以便事件循环可以更好地安排您的任务)。最后,您可能希望在几个线程之间批量处理请求,但这是最后的建议,因为协作多任务处理的重点是避免多线程。

    作为第一个赌注,即使在您开始分析代码以查看需要这么长时间的原因之前,请移除 sleep 行并查看您每秒发出多少请求。这将使您了解需要多少工作才能达到所需的吞吐量。

    【讨论】:

    • @e20byo,感谢您的回答。我也用信号量进行了测试。问题是,正如 Sraw 在这篇文章中提到的,这意味着“每秒完成的请求”,而不是“每秒发出的请求”(我真正需要的东西)
    • 确实如此。但是请看这里的其他点——从 no 完全限制(不睡觉)开始,看看发生了什么
    • 如果我取消睡眠,它会失败,原因是:无法连接到主机 XX.XX.X.XXX:XXXX ssl:default [无法分配请求的地址]
    • 有趣。好吧,您可以尝试短暂的睡眠,但这个想法只是为了了解您当前的代码 能够 查询的速度,因为这就是问题所在。我仍然认为这里的基本推理是:异步循环没有足够的时间来安排和解决所有连接。顺便尝试一下sleep(0),只是为了让调度程序能够移动到其他地方。但这只是分析。
    猜你喜欢
    • 2021-06-17
    • 1970-01-01
    • 1970-01-01
    • 2016-12-14
    • 1970-01-01
    • 2021-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多