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

异步编程中设置90秒超时却延迟触发ConnectTimeout的原因排查

问题背景

容器运行无限循环,从SQS拉取消息后,用asyncio信号量控制并发数为100,每条消息启动新协程处理。处理中通过httpx.AsyncClient调用外部API,全局超时设为90秒,但实际要等3分钟左右才抛出ConnectTimeout错误。本地对目标API做3500并发压测,超时设为20秒时仍有少量(0-5个)请求出现ConnectTimeout失败。

代码示例

try:
    self._async_client = AsyncClient(base_url=base_url, timeout=90)
    logging.info('starting')
    response = await self._async_client.post(self._SEARCH_ROUTE,
                                             json=request.dict(),
                                             params=self._get_common_params(account_name, request_id))
    logging.info('finished')
except httpx.ConnectTimeout as ex:
    print(f'I get here after 4 minutes')
排查方向
  • 明确超时配置的阶段拆分:httpx的全局超时可能未精准覆盖连接阶段。可以显式拆分连接超时和总请求超时,避免模糊逻辑导致超时失效:

    timeout = httpx.Timeout(90, connect=10)  # 单独限定连接阶段超时为10秒
    self._async_client = AsyncClient(base_url=base_url, timeout=timeout)
    
  • 检查系统级资源限制:容器环境下可能存在文件句柄不足、TCP连接队列长度不够的问题:

    • 查看容器的ulimit设置,确保打开文件数足够支撑并发连接(并发100建议预留200+文件句柄);
    • 目标API的TCP监听队列(backlog)过小会导致高并发下连接排队,超过超时时间才抛出错误,本地压测的少量失败也可能与此相关。
  • 排查DNS解析延迟:如果目标API的域名解析缓慢,会拉长连接阶段耗时。可以直接用IP调用API排除DNS问题,或在容器内用dig/nslookup多次测试域名解析耗时。

  • 修复连接池复用问题:代码中每次请求都新建AsyncClient,会导致连接无法复用,高并发下频繁TCP握手会占用资源引发排队超时。应在容器启动时创建一次客户端实例,所有协程共用:

    # 初始化阶段创建一次客户端
    self._async_client = AsyncClient(base_url=base_url, timeout=90)
    
    # 处理消息时直接复用
    try:
        logging.info('starting')
        response = await self._async_client.post(...)
        logging.info('finished')
    except httpx.ConnectTimeout as ex:
        ...
    
  • 排查网络中间件瓶颈:容器所在环境的代理、防火墙或负载均衡,在高并发下可能出现排队或处理延迟,导致连接请求被长时间挂起。可绕过中间件直接测试API连接,验证是否为中间件导致的延迟。

  • 检查目标API负载状态:本地压测时目标API若处于高负载状态,无法及时响应新连接请求会引发超时。查看目标API的CPU、内存、连接数指标,确认压测时是否达到性能瓶颈。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 08:05:11