无报错场景下AWS Lambda函数自动重复执行的原因排查
问题背景
我部署了一个作为负载均衡端点的AWS Lambda函数,该函数负责启动Fargate实例,并将实例注册到负载均衡下新建的目标组中。
该函数的预设执行工作流如下:
- 启动Fargate任务实例
- 创建目标组
- 为负载均衡创建监听器规则
- 等待任务进入运行状态
- 将Fargate任务注册为目标组的目标
- 等待任务通过健康检查并可正常响应请求
实际运行过程中,该函数有时会启动2个及以上Fargate实例,但首个启动的实例实际已经可以正常工作:通过HTTPS请求探测对应Fargate实例,可正常返回200状态码响应,但查看Lambda运行日志发现函数会自行重复执行,进而创建多余的Fargate实例。
关联Lambda运行日志
2022-07-01T15:23:48.623+02:00 START RequestId: 3a0c0b97-0a2b-444f-b1a3-89a98908826c Version: $LATEST 2022-07-01T15:23:49.584+02:00 ID : b21e58a3738e472d94b5f94cf5aae7ea 2022-07-01T15:23:57.401+02:00 Task attached ! 2022-07-01T15:24:10.230+02:00 Task running ! 2022-07-01T15:24:23.436+02:00 Target healthy ! 2022-07-01T15:24:23.729+02:00 response : b'{"message":"Flask server is running"}\n' 2022-07-01T15:24:23.729+02:00 Task responded ! 2022-07-01T15:24:23.783+02:00 END RequestId: 3a0c0b97-0a2b-444f-b1a3-89a98908826c 2022-07-01T15:24:23.783+02:00 REPORT RequestId: 3a0c0b97-0a2b-444f-b1a3-89a98908826c Duration: 35158.87 ms Billed Duration: 35159 ms Memory Size: 128 MB Max Memory Used: 71 MB Init Duration: 238.39 ms 2022-07-01T15:24:23.832+02:00 START RequestId: 587f3c66-bd63-4608-8bef-d406fde84ef8 Version: $LATEST 2022-07-01T15:24:23.881+02:00 ID : 4d7d6ca4570743f8838796bf8588b5b0 2022-07-01T15:24:30.214+02:00 Task attached ! 2022-07-01T15:24:43.890+02:00 Task running ! 2022-07-01T15:24:56.448+02:00 Target healthy ! 2022-07-01T15:24:56.693+02:00 response : b'{"message":"Flask server is running"}\n' 2022-07-01T15:24:56.693+02:00 Task responded ! 2022-07-01T15:24:56.761+02:00 END RequestId: 587f3c66-bd63-4608-8bef-d406fde84ef8 2022-07-01T15:24:56.761+02:00 REPORT RequestId: 587f3c66-bd63-4608-8bef-d406fde84ef8 Duration: 32925.84 ms Billed Duration: 32926 ms Memory Size: 128 MB Max M
核心问题
该Lambda函数在未出现运行报错的情况下自动重复执行的原因是什么?
答案
根本原因是Lambda执行超时触发了异步调用默认重试机制,日志特征完全匹配这个逻辑:
- 第一次函数执行总时长为35158.87ms(约35.16秒),说明你当前给Lambda配置的执行超时阈值为35秒,函数在即将返回成功响应的节点触发了超时判定,被Lambda服务强制标记为执行失败。
- AWS Lambda对异步触发的函数默认配置了2次自动重试规则:只要函数执行出现报错、超时,服务端会自动重新发起调用,不会判断前一次执行的业务逻辑是否已经实际完成。从时间戳也能验证:第一次执行标记结束到第二次执行启动仅间隔49毫秒,完全是服务端自动重试的时间特征。
- 你的函数没有做幂等校验,每次调用都会无条件执行新建Fargate任务、创建目标组的逻辑,所以重试触发后就会生成多余的运行实例。
对应的修复方向:
- 调大Lambda执行超时阈值,比如设置为1分钟以上,覆盖Fargate启动、注册、健康检查的全流程等待时长
- 增加幂等判断逻辑:启动Fargate任务前先查询当前是否已有符合要求的运行中、健康状态正常的任务,存在则直接返回,不重复创建资源
- 如果不需要异步重试能力,可以直接在Lambda异步调用配置里把重试次数改为0
内容的提问来源于stack exchange,提问作者JulienChamp
相关产品推荐
相关产品推荐

