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

Aiohttp会话关闭后连接仍存活,导致代理连接数持续增长问题

问题分析与解决方案

问题根源

你的代码中,每个异步任务的fetch_data函数在while True循环内反复创建新的ClientSession,每次会话关闭后,底层TCP连接因HTTP Keep-Alive机制会保持约10秒才销毁。30个任务持续循环创建会话,导致代理连接数不断累积,最终引发连接过载。

修复方案

1. 每个任务复用单一ClientSession

既然需求是每个任务保持同一代理IP,就应该让每个任务对应一个持久的ClientSession,在会话生命周期内循环执行请求,而非频繁创建销毁会话。修改后的核心逻辑如下:

import aiohttp
import asyncio

async def fetch_data():
    # 每个任务仅创建一次ClientSession,会话内保持固定代理IP
    async with aiohttp.ClientSession(
        connector=aiohttp.TCPConnector(keepalive_timeout=5)  # 缩短Keep-Alive超时加速连接回收
    ) as session:
        while True:
            try:
                response = await session.get(
                    'https://example.com/',
                    params=params, 
                    headers=headers, 
                    timeout=5,
                    proxy=proxys
                )
                result = await do_some(session)
                response = await session.get(
                    'https://example.com/',
                    params=params, 
                    headers=headers, 
                    timeout=5,
                    proxy=proxys
                )
                # 添加适当延迟,避免请求过于频繁
                await asyncio.sleep(0.5)
            except Exception as e:
                # 异常处理:打印错误、短暂重试
                print(f"请求出错: {str(e)}")
                await asyncio.sleep(1)
                continue

async def main():
    tasks = [asyncio.create_task(fetch_data()) for _ in range(30)]
    await asyncio.gather(*tasks)  # 等待所有任务执行,原代码未处理任务等待逻辑

if __name__ == "__main__":
    asyncio.run(main())

2. 关键优化点说明

  • 会话复用:每个任务的会话在while True外部创建,整个任务生命周期内复用同一个会话,避免频繁创建销毁带来的连接残留。
  • 调整Keep-Alive超时:通过TCPConnector的keepalive_timeout参数缩短闲置连接的存活时间,让代理端更快回收无效连接。
  • 完善任务等待:原main函数仅创建任务未等待执行,添加await asyncio.gather(*tasks)确保任务正常运行。
  • 添加请求延迟:在请求后加入短暂延迟,避免短时间内发送过多请求导致连接数激增。

额外建议

如果遇到代理IP失效需要切换的场景,可在异常分支中关闭当前会话并重新创建,而非一直复用失效的会话:

async def fetch_data():
    while True:
        try:
            async with aiohttp.ClientSession(connector=aiohttp.TCPConnector(keepalive_timeout=5)) as session:
                while True:
                    # 执行请求逻辑
                    await session.get(...)
                    await asyncio.sleep(0.5)
        except Exception as e:
            print(f"会话异常,将重新创建: {str(e)}")
            await asyncio.sleep(2)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 11:41:20