Asyncio aiohttp 实现每秒800次并行请求的方案正确性咨询
方案缺陷与问题原因
你的实现思路本身存在设计漏洞,实际速率只有预期的一半是正常现象,核心原因有3个:
asyncio.sleep调度精度不足
你设置的单次等待时长为1/800秒也就是1.25ms,而操作系统的事件调度本身存在精度损耗:Linux环境下通常有12ms的调度偏差,Windows环境默认定时器精度更是只有1015ms。每次等待的实际耗时都会比你设定的1.25ms更长,累计下来直接会将QPS砍半,刚好匹配你遇到的400QPS的情况。- 循环逻辑的额外开销
你在每次循环中除了等待,还要执行任务创建、参数组装的同步逻辑,这部分耗时也会挤占预设的间隔时间,进一步拉长单次循环的总耗时,拉低请求发起速率。 - aiohttp默认连接池限制
ClientSession默认的最大并发连接数仅为100,远低于你预期的800并发量级。超出连接数限制的请求会卡在等待空闲连接的队列中,就算你提前创建了异步任务也不会真的发起请求,自然达不到预期的QPS。
优化方案
- 调整连接池配置,创建
ClientSession时传入自定义的TCP连接器,放大连接数上限:
connector = aiohttp.TCPConnector(limit=1000) # 连接上限略高于预期并发即可 session = aiohttp.ClientSession(connector=connector)
- 替换逐次sleep的控速逻辑,改用令牌桶算法实现更稳定的速率控制,提前按800QPS的速率生成令牌,只有拿到令牌的任务才能发起请求,规避短sleep的调度精度损耗。
- 如果要保留现有循环逻辑,可将单次等待的步长调大,比如每创建4个任务统一sleep 5ms,减少短等待的次数,降低调度偏差带来的影响。
内容的提问来源于stack exchange,提问作者toni_92
相关产品推荐
相关产品推荐

