如何在S3新增对象时联动触发EC2运行Python脚本?
基于现有S3触发Lambda配置的EC2自动执行落地方案
通用前置配置(两种实现路径都需要提前完成)
- 给现有绑定S3事件的Lambda函数追加IAM权限:包含EC2实例状态查询、实例启动、SSM参数读写、SQS消息推送/消费的对应操作权限,不要硬编码密钥,用Lambda执行角色统一授权
- 提前完成EC2实例的基础配置:预装Python运行环境、脚本依赖包、目标Python脚本到固定本地路径;给EC2绑定带S3访问权限的实例角色,避免硬编码密钥;在UserData中配置启动自动执行逻辑,实现开机即触发后续流程,无需人工登录操作
- 补齐收尾逻辑:在目标Python脚本的最后增加自动停机命令,执行完文件处理流程后主动将EC2置为Stopped状态,避免持续产生资源成本
路径1:无缓冲直连触发(适合低文件上传频次场景)
完全基于现有已部署的S3-Lambda链路改造,无需新增队列组件:
- 修改现有Lambda的事件处理逻辑:收到S3新增文件事件后,先查询目标EC2的当前运行状态
- 若EC2已处于Running状态:直接通过SSM SendCommand将收到的文件所在的Bucket名、对象Key推送到EC2上,触发脚本立刻拉取文件处理
- 若EC2处于Stopped状态:将本次触发的文件信息(Bucket名、对象Key)存到SSM Parameter Store中,随后调用
start_instancesAPI启动目标EC2,Lambda执行完上述操作就直接退出,不要在Lambda中硬编码sleep逻辑等待EC2启动完成,避免触发超时
- 配置EC2启动后的自动流程:EC2开机进入系统后,通过UserData中的启动脚本先读取SSM Parameter里存储的待处理文件信息,执行
aws s3 cp s3://<目标桶>/<对象Key> <本地脚本输入路径>将文件从S3直接拉到本地(全程不经过Lambda中转,大文件也不会有带宽瓶颈),拉取完成后自动触发内置Python脚本运行
路径2:结合SQS削峰缓冲(适合高频文件上传场景)
针对短时间多次上传、可能重复触发的场景,通过SQS做消息缓冲,避免频繁启停EC2造成的资源浪费:
- 新增标准SQS队列,调整现有Lambda逻辑:收到S3新增文件事件后,不直接操作EC2,直接把事件中的Bucket名、对象Key、上传时间等信息作为消息推送到SQS队列,Lambda直接退出
- 配置定时检查规则:通过EventBridge设置1-5分钟间隔的定时触发规则,每次触发Lambda查询队列内的待处理消息数
- 若队列内存在待处理消息,且EC2处于Stopped状态,就调用
start_instances启动EC2 - 若EC2已经处于Running状态,就直接通过SSM SendCommand把队列里的待处理消息列表推送到EC2上
- 若队列内存在待处理消息,且EC2处于Stopped状态,就调用
- 调整EC2侧的处理逻辑:EC2启动后自动轮询SQS队列的待处理消息,逐个从S3拉取对应文件到本地,全部处理完成后将对应消息从队列删除,最后触发脚本内置的自动停机逻辑
关键注意事项
- 做好幂等判断:S3事件通知存在重复投递的概率,EC2侧处理文件时要记录已处理的文件Key日志,遇到重复消息直接跳过,避免重复执行脚本
- 不要用Lambda中转文件:大文件场景下Lambda的内存、带宽配额有限,直接让EC2通过自身实例角色权限从S3拉取文件,传输效率更高,也不会占用Lambda的运行资源
- 避免超时问题:EC2从启动到系统就绪通常需要几十秒,不要在Lambda中等待EC2状态变为Running就推送任务,所有状态等待逻辑全部放到EC2启动后的自启动脚本中完成
内容的提问来源于stack exchange,提问作者akshay acharya
相关产品推荐
相关产品推荐

