You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Lambda2调用S3 HeadObject报404,疑文件未同步完成

解决Lambda2因S3文件未就绪导致的404错误

问题场景

Lambda1调用AWS Transcribe生成SRT文件并存入S3,随后将文件存储位置传递给Lambda2;Lambda2尝试下载该文件时触发ClientError: An error occurred (404) when calling the HeadObject operation: Not Found错误。但直接用S3触发器触发Lambda2时代码可正常运行,核心原因是Transcribe生成的SRT文件尚未完全写入S3,Lambda2就开始执行下载操作。

解决方案

方案1:改用S3事件触发器替代Lambda直接调用

既然S3触发器能保证文件写入完成后再触发Lambda2,可调整架构:

  • 让Lambda1仅负责启动Transcribe任务,无需直接调用Lambda2
  • 给存储SRT文件的S3桶配置s3:ObjectCreated:*事件,将Lambda2设为事件目标
  • 好处:完全由S3的事件机制保证文件就绪后再执行处理逻辑,从根源避免时序问题

方案2:在Lambda2中添加重试机制

如果必须保留Lambda1调用Lambda2的链路,可在下载逻辑中加入重试逻辑,等待文件就绪:

import boto3
import urllib.parse
from botocore.exceptions import ClientError
import time

s3 = boto3.resource('s3')

def lambda_handler(event, context):
    source_bucket_name = event['responsePayload']['BucketDestination']
    file_name = urllib.parse.unquote_plus(event['responsePayload']['ObjectKey'])
    source_file = '/tmp/source.srt'
    
    # 配置重试参数:最多5次,每次间隔2秒
    max_retries = 5
    retry_count = 0
    
    while retry_count < max_retries:
        try:
            source_object = s3.Object(source_bucket_name, file_name)
            source_object.download_file(source_file)
            print("文件下载成功")
            break
        except ClientError as e:
            if e.response['Error']['Code'] == '404':
                retry_count += 1
                print(f"文件未找到,第{retry_count}次重试...")
                time.sleep(2)
            else:
                # 非404错误直接抛出
                raise
    else:
        # 重试耗尽仍失败,抛出异常
        raise Exception(f"重试{max_retries}次后仍无法找到文件:{file_name}")
  • 注意:需将Lambda2的执行超时时间设置为足够长(建议至少15秒),避免重试过程中被强制终止

方案3:让Lambda1等待Transcribe任务完成再调用Lambda2

修改Lambda1逻辑,轮询等待Transcribe任务完成后,再调用Lambda2:

import boto3
import json
import time

transcribe = boto3.client('transcribe')
lambda_client = boto3.client('lambda')

def lambda_handler(event, context):
    # 启动Transcribe任务的原有逻辑
    job_name = 'test_short49'
    transcribe.start_transcription_job(
        TranscriptionJobName=job_name,
        Media={'MediaFileUri': 's3://your-input-bucket/input-file.mp3'},
        OutputBucketName='bucket-1',
        OutputKey='test_short49',
        Subtitles={'Formats': ['srt']}
    )
    
    # 轮询等待任务完成
    while True:
        job_status = transcribe.get_transcription_job(TranscriptionJobName=job_name)['TranscriptionJob']['TranscriptionJobStatus']
        if job_status in ['COMPLETED', 'FAILED']:
            break
        time.sleep(3)
    
    if job_status == 'COMPLETED':
        # 获取最终SRT文件的存储位置
        bucket = 'bucket-1'
        object_key = f"{job_name}.srt"
        # 调用Lambda2
        lambda_client.invoke(
            FunctionName='Lambda2',
            Payload=json.dumps({
                'responsePayload': {
                    'BucketDestination': bucket,
                    'ObjectKey': object_key
                }
            })
        )
  • 注意:需根据Transcribe任务的预期耗时,设置Lambda1的超时时间(比如如果任务通常需要1分钟,超时设为2分钟)

内容的提问来源于stack exchange,提问作者user3324136

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 18:52:43