如何在Lambda函数中实现S3的Fire-and-forget上传以缩减运行耗时
结论
你想要的在Lambda内部实现上传操作Fire-and-forget、无需等待完成就返回的需求无法直接实现,你必须用异步解耦的架构来规避主Lambda等待上传的耗时成本,不可能在单Lambda进程内绕过这个限制。
核心限制原因
Lambda运行时一旦检测到函数返回响应,会立刻冻结甚至销毁整个执行环境,所有未完成的后台任务(包括你用asyncio.create_task创建的未执行协程、后台线程提交的同步任务)都会直接中断,这就是你遇到「Task was destroyed but it is pending!」报错的根本原因,和你用的Boto3客户端是否异步无关。
就算你替换为真异步的aioboto3库替代原生同步Boto3,也无法解决提前返回导致的任务中断问题。
可行的低成本替代方案
完全可以实现主Lambda无需等待S3/DynamoDB上传完成就结束计费,只需要做简单的异步解耦即可:
- 方案1:引入SQS队列做异步缓冲
主Lambda计算逻辑完成后,把需要上传的元数据、S3存储路径、DynamoDB写入参数等信息打包成消息,调用sqs.send_message发送到标准SQS队列即可直接返回,SQS发消息的耗时普遍在10ms以内,远低于S3上传耗时。
额外配置SQS队列触发另一个专用的上传Lambda,由这个异步Lambda执行S3put_object和DynamoDB写入操作,这部分耗时完全不计入主Lambda的计费。如果要求严格不重复写入,可以把SQS队列替换为FIFO队列。 - 方案2:用EventBridge做事件路由(适合小体积元数据)
如果要上传的元数据体积小于256KB,可以直接把元数据打包成EventBridge事件发送,主Lambda发完事件立刻返回。后续配置EventBridge规则,直接触发目标S3桶写入、DynamoDB表写入,不需要额外维护上传Lambda,架构更简单。
额外优化建议
如果因为架构限制暂时不能做解耦,你可以将原有的同步Boto3替换为aioboto3异步客户端,同时开启S3传输加速、同区域部署S3桶,能大幅降低并行上传的耗时,减少Lambda计费时长。
内容的提问来源于stack exchange,提问作者Gabriel Lefundes
相关产品推荐
相关产品推荐

