Python asyncio 并发请求实践小结:从 gather 到信号量限流

举报
flashmind 发表于 2026/10/30 15:33:04 2026/10/30
【摘要】 在日常开发中,我们经常需要同时调用多个 HTTP 接口,比如批量拉取数据、并行检查服务状态等。如果使用同步的 requests 逐个请求,总耗时等于所有请求耗时之和。借助 Python 标准库 asyncio 配合 aiohttp,可以把这些 I/O 等待时间重叠起来,大幅缩短整体耗时。一、基本用法:asyncio.gather最简单的方式是为每个请求创建一个协程,再用 asyncio.ga...

在日常开发中,我们经常需要同时调用多个 HTTP 接口,比如批量拉取数据、并行检查服务状态等。如果使用同步的 requests 逐个请求,总耗时等于所有请求耗时之和。借助 Python 标准库 asyncio 配合 aiohttp,可以把这些 I/O 等待时间重叠起来,大幅缩短整体耗时。

一、基本用法:asyncio.gather

最简单的方式是为每个请求创建一个协程,再用 asyncio.gather 一次性并发执行。gather 会按传入顺序返回结果,写法直观。需要注意的是,默认情况下只要有一个协程抛出异常,gather 就会把异常向上抛出;如果希望单个失败不影响整体,可以传入 return_exceptions=True,再逐个判断结果是否为异常对象。

二、控制并发数:asyncio.Semaphore

当请求数量达到成百上千时,一次性全部发出容易触发对端限流,甚至耗尽本地连接资源。此时可以创建一个 asyncio.Semaphore(10) 之类的信号量,在每个请求协程内部用 async with sem 包裹真正的请求逻辑,这样同一时刻最多只有 10 个请求在进行,其余请求会排队等待。

三、超时与重试

网络请求一定要设置超时。aiohttp 可以通过 ClientTimeout 统一设置总超时时间,也可以用 asyncio.wait_for 为单个协程设置超时。对于偶发失败,可以写一个简单的重试循环,每次失败后用 asyncio.sleep 做指数退避,避免在对端故障时持续加压。

四、复用会话

不要为每个请求单独创建 ClientSession。会话内部维护了连接池,整个批量任务共用一个 session,可以复用 TCP 连接,减少握手开销。通常的做法是在主协程中 async with aiohttp.ClientSession() as session,然后把 session 作为参数传给各个请求协程。

五、小结

asyncio 并不会让单个请求变快,它的价值在于让多个 I/O 等待并行发生。gather 负责并发调度,Semaphore 负责限流,超时与重试保证健壮性,共享会话降低开销。把这几点组合起来,就能写出既高效又稳定的批量请求代码。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。