Google Cloud Run对外API调用速度异常缓慢的排查求助
问题概述
部署在Google Cloud Run的FastAPI应用,发起100次外部API请求时,延迟会毫无预兆地突然飙升(从0.02秒级跳到十几甚至几十秒),本地测试平均延迟仅0.0245秒(快547倍)。已配置静态出口IP、升级实例资源(内存/vCPU),问题依旧。
简化后的核心代码:
@app.post("/") async def handle_jsonrpc(request: Request, background_tasks: BackgroundTasks): # 启动任务调用example.com 100次 asyncio.create_task(latency_test()) return JSONResponse("ok", status_code=200)
Cloud Run测试日志片段:
2025-05-15 18:37:33 INFO:main:Request 095: 0.0222 seconds (status 200)
2025-05-15 18:37:32 INFO:main:Request 084: 20.1998 seconds (status 200)
2025-05-15 18:37:39 INFO:main:Request 081: 39.6005 seconds (status 200)
On Google Cloud: Avg latency per request: 13.4155 seconds.
排查方向与解决方案
1. 调整异步HTTP客户端的连接池配置
异步HTTP客户端(如httpx、aiohttp)默认连接池容量有限,当并发请求数超过池上限时,会等待空闲连接释放,导致延迟骤增。建议显式配置匹配请求规模的连接池:
import httpx # 初始化客户端时设置连接池参数 client = httpx.AsyncClient( limits=httpx.Limits( max_connections=100, # 匹配请求总数 max_keepalive_connections=50 ) )
2. 限制并发请求数量
Cloud Run对出口请求存在隐性速率限制,瞬间发起大量并发请求可能触发临时限流。用asyncio.Semaphore控制同时执行的请求数:
async def latency_test(): semaphore = asyncio.Semaphore(10) # 限制同时10个请求 tasks = [] for i in range(100): tasks.append(asyncio.create_task(fetch_with_semaphore(semaphore, i))) await asyncio.gather(*tasks) async def fetch_with_semaphore(sem, req_id): async with sem: async with client.get("https://www.example.com") as resp: # 记录延迟逻辑 pass
3. 替换asyncio.create_task为FastAPI的background_tasks
自行调用asyncio.create_task启动的任务,可能在请求响应返回后,因Cloud Run实例的事件循环回收而被中断或调度异常。改用FastAPI提供的background_tasks.add_task确保任务稳定执行:
@app.post("/") async def handle_jsonrpc(request: Request, background_tasks: BackgroundTasks): # 改用background_tasks添加任务 background_tasks.add_task(latency_test) return JSONResponse("ok", status_code=200)
4. 排查DNS解析延迟
Cloud Run环境下的DNS解析可能出现波动,建议提前解析目标域名的IP,直接通过IP发起请求(需手动设置SNI以支持HTTPS):
import socket # 提前解析example.com的IP(可缓存) target_ip = socket.gethostbyname("www.example.com") # 发起请求时指定IP和主机头 async with client.get(f"https://{target_ip}", headers={"Host": "www.example.com"}) as resp: pass
5. 查看Cloud Run网络监控指标
通过Google Cloud Console查看以下指标,定位网络瓶颈:
- 实例的出口带宽使用率
- TCP连接建立时间(SYN到ACK的延迟)
- 数据包丢失率
- VPC Connector(若使用)的日志,确认是否有连接限流
内容的提问来源于stack exchange,提问作者Yason

