Google Cloud Run执行GET请求时遭遇SSLEOFError的问题求助
问题:Google Cloud Run中FastAPI应用GET请求SSL异常问题
问题现象
- 基于Python 3.10+FastAPI的应用部署在Google Cloud Run,POST请求正常,但GET请求仅在云端运行时失败,本地运行同一容器完全正常
- 报错信息:
SSLEOFError(8, '[SSL: UNEXPECTED_EOF_WHILE_READING] EOF occurred in violation of protocol (_ssl.c:1007) - 补充排查结论:GET请求首次调用成功,后续重复调用触发SSL错误;即使设置
verify=False仍无法解决;在Google云VM上直接运行Python代码执行该GET请求可正常工作
相关代码与配置
核心业务代码
app = FastAPI() @app.on_event("startup") async def init() -> None: """ Initialize variables to start app """ if co.DEV: res = whatsapp.send_msg_to_test_group("DEV Deployment is Up!", co.TEST_WHATSAPP_GROUP_ID) logging.info(res) else: logging.info("Production is Up!") @app.on_event("startup") @repeat_every(seconds=60, wait_first=False, logger=toko_logger, raise_exceptions=co.RAISE_EXCEPTIONS) async def test_api() -> None: import requests for i in range(3): resp = requests.request("GET", url=<MY_URL>, headers=<HEADERS>) logger.debug(f"details: {len(resp.json())}") sleep(10)
依赖清单(requirements.txt)
fastapi==0.104.0 fastapi-utils==0.2.1 requests==2.31.0 uvicorn==0.24.0.post1
Docker启动命令
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8080", "--reload"]
原因分析
- 连接复用冲突:requests默认启用HTTP Keep-Alive复用TCP连接,但Cloud Run的网络代理/底层环境对长连接有严格超时或回收策略,首次请求后连接被远端强制关闭,requests仍尝试复用失效连接,导致SSL读取时触发EOF错误
- 异步环境与同步库不兼容:
test_api是异步函数,但内部使用了同步的requests和sleep,在FastAPI的异步事件循环中运行同步IO操作,容易导致连接状态紊乱,在Cloud Run资源受限的容器环境下更易触发问题 - Cloud Run网络层特殊限制:虽然云VM可正常请求,但Cloud Run的外部访问路径经过专属代理层,对重复GET请求的连接处理逻辑与普通VM不同,比如连接超时阈值更低
解决方法
方法1:强制禁用requests连接复用
修改GET请求代码,避免复用失效连接:
# 方式一:通过Session限制连接池 session = requests.Session() adapter = requests.adapters.HTTPAdapter(pool_connections=1, pool_maxsize=1) session.mount("https://", adapter) resp = session.request("GET", url=<MY_URL>, headers=<HEADERS>) # 方式二:添加Connection: close头部强制关闭连接 headers = <HEADERS>.copy() headers["Connection"] = "close" resp = requests.request("GET", url=<MY_URL>, headers=headers)
方法2:改用异步HTTP库适配环境
替换同步的requests为异步的httpx,适配FastAPI的异步事件循环:
- 更新requirements.txt,添加依赖:
httpx==0.25.2
- 修改定时任务代码:
import httpx import asyncio @app.on_event("startup") @repeat_every(seconds=60, wait_first=False, logger=toko_logger, raise_exceptions=co.RAISE_EXCEPTIONS) async def test_api() -> None: async with httpx.AsyncClient() as client: for i in range(3): resp = await client.get(url=<MY_URL>, headers=<HEADERS>) logger.debug(f"details: {len(resp.json())}") await asyncio.sleep(10)
方法3:调整Cloud Run配置与启动参数
- 移除Docker启动命令中的
--reload参数,该参数为开发模式专用,生产环境使用会导致容器进程不稳定:
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8080"]
- 尝试配置Cloud Run的VPC连接器,让应用通过VPC直接访问外部服务,绕过默认网络代理
- 检查并延长Cloud Run服务的实例超时时间,确保覆盖定时任务的执行周期
内容的提问来源于stack exchange,提问作者Shani Shalgi
相关产品推荐
相关产品推荐

