FastAPI部署GCP Cloud Run上传媒体遇504超时错误求助
GCP Cloud Run部署FastAPI后端出现504 upstream request timeout问题
本地运行完全正常,但部署到GCP Cloud Run后,调用/create-pharmacy-user-form接口连续数日出现504 : upstream request timeout错误。相关代码如下:
接口代码
@router.post("/create-pharmacy-user-form", status_code=status.HTTP_201_CREATED) async def create_form_user( db: db_dependency, # Database dependency user_email: str = Form(...), user_password: str = Form(...), user_first_name: str = Form(...), user_last_name: str = Form(...), user_phone_number: str = Form(...), user_city: str = Form(...), user_country: str = Form(...), local_name: str = Form(...), user_newsletter_subscription: bool = Form(...), local_image: UploadFile = File(...), local_ice: UploadFile = File(...), local_patent: UploadFile = File(...) ): user_interface = UserInterface(db) try: # transform base 64 to file print("Endpoint called") user_data = { "user_email": user_email, "user_password": user_password, "user_first_name": user_first_name, "user_last_name": user_last_name, "user_phone_number": user_phone_number, "user_city": user_city, "user_country": user_country, "local_name": local_name, "local_image": local_image, "local_ice": local_ice, "local_patent": local_patent, "user_newsletter_subscription": user_newsletter_subscription, } db_user = user_interface.create_pharmacy_user(user_data) print("Uploading image") # Call the image upload function (ensure this is atomic or does not affect DB consistency) try : post_images(db_user["local_id"], user_data["local_image"], "pharmacy_images") print("Image uploaded") # Upload documents post_document(db_user["user_id"], user_data["local_ice"], "pharmacy_ices") post_document(db_user["user_id"], user_data["local_patent"], "pharmacy_patents") print("Documents uploaded") except Exception as e: print(e) #posting media return api_response( message="User created successfully", data=db_user, status_code=201 ) except Exception as e: return api_response( message="User creation failed: " + str(e), status_code=500 )
文件上传函数代码
def post_images(image_id: uuid.UUID, image_file: UploadFile, path: str): bucket_name = settings.BUCKET_NAME service_account_json = settings.SERVICE_ACCOUNT_JSON try: # Open image directly from UploadFile's file object print("Opening image file") # Initialize GCS client client = storage.Client.from_service_account_json(service_account_json) bucket = client.bucket(bucket_name) # Generate a unique blob name blob_name = f"{path}/{image_id}.webp" blob = bucket.blob(blob_name) # Upload image to GCS blob.upload_from_file(image_file.file, content_type=image_file.content_type) print("Image uploaded successfully") print(blob.public_url) return {"image_id": str(image_id), "url": blob.public_url} except Exception as e: print("Error uploading image:", e) raise HTTPException(status_code=500, detail="Image upload failed.") def post_document(document_id: uuid.UUID, document_file: UploadFile, path: str): bucket_name = settings.BUCKET_NAME service_account_json = settings.SERVICE_ACCOUNT_JSON try: # Read the file asynchronously print("Reading Document file") # Guess the mime type of the file mime_type = mimetypes.guess_type(document_file.filename)[0] or "application/octet-stream" extension = mimetypes.guess_extension(mime_type) or ".bin" # Create a file-like object in memory # Generate a unique file name with the correct extension blob_name = f"{path}/{document_id}{extension}" # Initialize GCS client client = storage.Client.from_service_account_json(service_account_json) bucket = client.bucket(bucket_name) blob = bucket.blob(blob_name) # Upload the file to GCS asynchronously blob.upload_from_file(document_file.file, content_type=mime_type) print("Document uploaded") print(blob.public_url) return True except Exception as e: print("Error uploading document:", e) raise HTTPException(status_code=500, detail="Document upload failed.")
排查与解决建议
- 调整Cloud Run超时配置:Cloud Run默认请求超时为5分钟,若文件上传耗时较长,需在Cloud Run服务设置中延长超时时间(最大可设为60分钟)。
- 优化GCS客户端初始化:每次上传都重新初始化GCS客户端会增加开销,建议全局复用客户端实例,避免重复创建连接。
- 异步化文件上传操作:当前接口在同步线程中执行文件上传,可改用异步GCS客户端,或把文件上传任务放入后台队列(如Cloud Tasks),先返回用户创建成功的响应,再异步处理上传,避免请求超时。
- 检查文件上传大小限制:Cloud Run单请求最大 payload 限制为32MB,若上传文件总大小接近或超过该值,会导致请求处理超时,需拆分请求或改用分片上传。
- 添加日志与监控:在文件上传的关键节点增加详细日志,结合Cloud Logging查看请求处理的耗时分布,定位具体是数据库操作还是文件上传环节超时;同时配置Cloud Monitoring的请求超时告警,便于实时排查。
- 验证服务账号权限:确保Cloud Run服务账号拥有GCS存储桶的写入权限,权限不足可能导致上传停滞引发超时。
- 优化文件上传方式:使用
blob.upload_from_file时,可设置chunk_size参数(如chunk_size=1024*1024)分块上传,提升大文件上传的稳定性。
内容的提问来源于stack exchange,提问作者RedBlue197
相关产品推荐
相关产品推荐

