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

使用aiohttp通过SSH代理隧道异步请求时遇‘Server Disconnected’错误

解决aiohttp异步请求通过SSH SOCKS代理时出现Server disconnected的问题

问题场景

通过以下命令建立SSH动态SOCKS5代理隧道:

sshpass -p "<my_pass>" ssh -D 8090 my_user@my_server.com

同步HTTP请求(如requests结合socks代理)可正常工作,但使用aiohttp发起异步请求时,频繁触发ServerDisconnectedError,无代理或同步请求时无此问题。


解决方案

1. 优化SSH隧道的存活配置

SSH服务器默认会断开长时间空闲的连接,异步请求的连接模式更容易触发该机制。修改SSH命令,添加保活参数:

sshpass -p "<my_pass>" ssh -D 8090 -o ServerAliveInterval=30 -o ServerAliveCountMax=5 my_user@my_server.com
  • ServerAliveInterval=30:每30秒向SSH服务器发送一次存活检测包
  • ServerAliveCountMax=5:连续5次检测无响应才主动断开连接

2. 复用aiohttp ClientSession

原代码中每次请求都创建新的ClientSession,会频繁与SOCKS代理建立新连接,增加断开风险。改为复用Session实例:

async def _resilient_request(
    self, url: str, headers: Dict[str, str]
) -> Dict[str, Any]:

    proxy = "socks5h://localhost:8090"
    # 新增连接超时设置,避免连接代理时长时间等待
    timeout = aiohttp.ClientTimeout(total=30, connect=10)

    # 把ClientSession创建移到循环外,复用连接池
    async with aiohttp.ClientSession(
        timeout=timeout, json_serialize=ujson.dumps,
    ) as session:
        for attempt in range(8):
            try:
                async with session.get(url, headers=headers, ssl=False, proxy=proxy) as resp:
                    resp.raise_for_status()
                    data = await resp.json()
                    return data
            except (
                aiohttp.ClientError,
                aiohttp.ClientResponseError,
                asyncio.TimeoutError,
                aiohttp.ServerDisconnectedError,
                aiohttp.ClientConnectorError,
                RuntimeError,
            ) as err:
                if attempt < 3:
                    await asyncio.sleep(attempt + 1)
                    print(f"Resilient request failed. Retrying attempt {attempt + 1}")
                    print(f"Error: {err}")
                    continue
                else:
                    raise err

3. 使用专用SOCKS代理库提升兼容性

如果原生aiohttp的SOCKS支持存在兼容性问题,改用aiohttp-socks库处理代理:

  1. 安装依赖:
pip install aiohttp-socks
  1. 修改代码中的Session配置:
from aiohttp_socks import ProxyConnector

async def _resilient_request(
    self, url: str, headers: Dict[str, str]
) -> Dict[str, Any]:

    # 用专用连接器配置SOCKS代理
    connector = ProxyConnector.from_url("socks5h://localhost:8090")
    timeout = aiohttp.ClientTimeout(total=30, connect=10)

    async with aiohttp.ClientSession(
        connector=connector, timeout=timeout, json_serialize=ujson.dumps,
    ) as session:
        for attempt in range(8):
            try:
                # 无需再单独传proxy参数
                async with session.get(url, headers=headers, ssl=False) as resp:
                    resp.raise_for_status()
                    data = await resp.json()
                    return data
            except (...) as err:
                # 保持原异常处理逻辑不变
                pass

4. 检查并发连接限制

SSH动态隧道或目标服务器可能对并发连接数有限制,可尝试降低异步请求的并发量,或联系服务器管理员调整SSH服务的MaxSessions配置(若权限允许)。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 23:22:45