You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何循环顺序发起请求时aiohttp仍比requests更快?

为什么顺序发起请求时aiohttp比requests更快?

我分别用aiohttp和requests通过for循环顺序发起HTTP GET请求,代码如下:

aiohttp实现代码

import aiohttp
import asyncio
import time

start_time = time.time()


async def main():
    async with aiohttp.ClientSession() as session:
        for num in range(1, 10):
            pokemon_url = f'https://pokeapi.co/api/v2/pokemon/{num}'
            async with session.get(pokemon_url) as response:
                pokemon_json = await response.json()
                print(pokemon_json['name'], num)


asyncio.run(main())

print(f'{time.time() - start_time} seconds')

我原本认为这段代码的for循环会同步执行session.get,每次循环里的await会让main协程暂停,事件循环没其他协程可跑,只能等响应返回,异步的性能优势没体现出来。

requests实现代码

import requests
import time

start_time = time.time()

for num in range(1, 10):
    url = f'https://pokeapi.co/api/v2/pokemon/{num}'
    response = requests.get(url)
    pokemon = response.json()
    print(pokemon['name'])

print(f'{time.time() - start_time} seconds')

实际测试下来,aiohttp耗时3.58秒左右,requests耗时8.43秒左右。既然都是顺序发起请求,为什么aiohttp还是更快?


回答

核心原因在于底层IO模型的差异:

  • requests基于同步阻塞的socket实现,发起请求后,整个线程会被完全阻塞,直到服务器返回响应——这段等待时间里线程什么都做不了,只能空等。
  • aiohttp基于异步非阻塞的socket实现,当await session.get()时,虽然当前协程会暂停,但事件循环可以利用这段等待时间去处理其他底层IO操作(比如socket的读写就绪事件、系统信号等),不会让CPU空转。哪怕没有其他协程,异步IO的底层调度效率也比同步阻塞更高,因为它避免了同步IO中线程上下文切换、内核态/用户态频繁切换的额外开销。

另外,aiohttp的ClientSession会复用连接池,在顺序请求时能减少TCP握手、TLS协商的重复开销;而requests虽然也支持连接池,但默认配置和异步实现的连接复用效率有差距。

还有一点:await response.json()在aiohttp里是异步解析JSON,不会阻塞事件循环;而requests的response.json()是同步解析,会占用线程时间。

总结下来,哪怕是顺序请求,异步IO的底层机制依然能带来性能提升,主要体现在减少空等时间、降低系统开销上。


内容的提问来源于stack exchange,提问作者CyberPlayerOne

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 05:52:43