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

Cloud Run中Python Requests调用API遇SSLZeroReturnError问题求助

问题分析与解决方案

核心原因

FastAPI的BackgroundTasks默认用线程池执行后台任务,当大量请求触发任务时,requests默认的连接池会因为连接复用不当、未及时释放,加上Cloud Run容器的套接字数量/连接超时限制,导致连接被中途关闭,出现SSLZeroReturnError。本地运行无问题是因为本地资源限制宽松,并发压力小。

具体解决方案

1. 用requests.Session复用连接并配置连接池参数

requests.Session会自动复用TCP连接,减少套接字创建量,同时可通过urllib3参数控制最大连接数,避免超限。

修改请求函数:

import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

# 服务启动时初始化全局Session,只创建一次
serper_session = requests.Session()
# 配置重试策略与连接池参数
retry_strategy = Retry(
    total=3,
    backoff_factor=1,
    status_forcelist=[429, 500, 502, 503, 504],
    allowed_methods=["POST"]
)
adapter = HTTPAdapter(
    max_retries=retry_strategy,
    pool_connections=10,  # 控制同时打开的连接池数量
    pool_maxsize=10       # 每个连接池的最大连接数
)
serper_session.mount("https://", adapter)

def serper_search(self, arguments):
    query = arguments["q"]
    url = "https://google.serper.dev/search"
    payload = {"q": query}  # 直接传字典,requests自动序列化JSON,无需手动dumps
    headers = {
        'X-API-KEY': self.api_key,
        'Content-Type': 'application/json'
    }

    try:
        # 使用全局Session发起请求
        response = serper_session.post(url, headers=headers, json=payload)
        response.raise_for_status()
        
        # 读取内容后显式关闭连接,释放回连接池
        response_content = response.json()
        response.close()
        
        parsed_response = self.parse_response(response_content, number_of_results=3)
        return parsed_response
    except requests.exceptions.HTTPError as http_err:
        logger.error(f"HTTP error occurred: {http_err}")
        return None
    except Exception as e:
        logger.error(f"Error occurred: {e}")
        return None

2. 限制BackgroundTasks的线程池大小

FastAPI默认后台任务线程池大小为CPU核心数*5,在Cloud Run容器环境中(通常核心数有限),手动调整线程池大小可避免并发任务过多导致连接超限。

修改FastAPI主文件:

from fastapi import FastAPI, BackgroundTasks
from concurrent.futures import ThreadPoolExecutor

# 自定义线程池,根据Cloud Run资源调整并发数(1核实例建议设为5-10)
executor = ThreadPoolExecutor(max_workers=5)

app = FastAPI()

@app.post("/message", tags=["Main"])
async def handle_message(background_tasks: BackgroundTasks, message):
    # 用自定义线程池执行后台任务
    background_tasks.add_task(executor.submit, serper_search, message)
    return {"success": True}

3. 显式释放响应资源

读取响应内容后调用response.close(),确保连接被释放回连接池,避免套接字泄漏。

4. 调整Cloud Run容器配置

  • 提升CPU/内存配额:资源不足会导致连接处理不及时,被系统强制关闭
  • 延长请求超时:在Cloud Run控制台设置更长的请求超时,避免后台任务未完成时连接被切断

验证逻辑

去掉BackgroundTasks时无错误,说明核心问题是后台任务的并发连接数超限,通过上述方案限制并发、复用连接后,可解决SSLZeroReturnError问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 19:12:17