aiohttp请求为何额外增加约100秒延迟?
aiohttp请求客户端耗时远高于服务端的原因分析
从你提供的代码和日志来看,服务端仅统计了自身处理请求的时间(9.41秒),而客户端计时包含了从请求发起、网络传输到响应接收的全链路时间,额外开销大概率来自以下几个方面:
TCP连接复用问题
你当前每次请求都新建ClientSession,而session默认维护连接池。如果是首次请求或连接池无可用连接,需要重新完成TCP三次握手(HTTPS还需TLS握手),这部分耗时服务端不会统计。若网络环境不稳定,握手阶段可能出现重试或阻塞,直接拉长客户端总耗时。建议复用ClientSession(比如在程序启动时创建一次,后续请求复用),避免重复建立连接的开销。网络传输的双向延迟
服务端日志的耗时是自身从接收完请求到发送完响应的处理时间,但客户端计时包含:- 请求体(104条消息的JSON payload)上传到服务端的时间;
- 服务端处理时间;
- 响应体从服务端传输回客户端的时间。
如果payload体积较大,或网络带宽不足、存在丢包重传,上传/下载阶段的延迟会被算进客户端总耗时,这部分服务端不会统计。
事件循环被阻塞
aiohttp依赖异步事件循环运行,如果你的代码在同事件循环中存在同步阻塞操作(比如CPU密集计算、同步IO、调用time.sleep()),会导致事件循环无法及时处理aiohttp的网络IO回调,看起来像是请求耗时变长。检查是否有其他同步任务占用了事件循环的执行时间。连接池排队限制
如果客户端存在并发请求,ClientSession的连接池配置(比如limit、limit_per_host)过低会导致新请求排队等待可用连接,排队时间会被计入客户端计时,但服务端无感知。可以调整连接池的最大连接数参数,避免排队。
验证建议
- 拆分计时:在
session.post调用前、获取response后、await response.json()后分别记录时间,定位哪一阶段耗时最长; - 复用Session:将
ClientSession的创建移到请求循环外,复用连接后观察耗时变化; - 隔离阻塞操作:用
asyncio.get_event_loop().run_in_executor()把同步阻塞任务放到线程池,避免阻塞事件循环; - 抓包分析:用tcpdump或Wireshark抓取请求的TCP包,查看连接建立、数据传输过程是否有延迟或重传。
内容的提问来源于stack exchange,提问作者Vahe Tshitoyan
相关产品推荐
相关产品推荐

