AWS Lambda中s3.putObject()上传成功却无返回的问题排查
问题描述
我们在AWS Lambda函数中运行以下上传文件至AWS S3的代码:
import AWS from 'aws-sdk'; const s3 = new AWS.S3(); export async function putObjectToS3( data: any, nameOfFile: string, contentType: string ) { const params = { Bucket: process.env.S3_BUCKET || '', ContentType: contentType, Key: `${nameOfFile}`, Body: data }; console.log('start s3 put object'); const response = await s3.putObject(params).promise(); console.log('end s3 put object: ', response); return response; } await putObjectToS3(artistsCsv, `artists/artists.csv`, 'text/csv');
目前artistsCsv文件已成功上传至S3(可在S3中看到该CSV文件),但函数始终无法返回。日志中仅能看到start s3 put object,却从未出现end s3 put object: , response。
使用的aws-sdk版本为^2.1147.0,请问:
- 函数写法是否存在问题导致无法返回response?
- 是否可能是AWS自身问题?
- 或是在
.promise()与async/await的使用上存在疏漏? - 该如何排查此问题?
分析与解决方案
1. 函数写法的潜在问题
- Lambda入口处理疏漏:直接在顶层使用
await putObjectToS3(...)是核心问题之一。Lambda的初始化阶段与执行阶段分离,顶层代码在初始化时运行,而handler才是执行阶段的入口。如果异步调用不在handler内部,Lambda可能在异步操作完成前就终止执行环境,导致后续日志和返回逻辑无法触发。 - Bucket参数校验缺失:
process.env.S3_BUCKET || ''在环境变量未配置时会传入空Bucket名,但当前上传成功说明Bucket有效,可后续添加参数校验避免异常。
2. AWS自身问题的可能性
可能性极低。文件已成功上传,说明s3.putObject的核心操作已完成。若AWS服务端异常,通常会返回明确错误而非静默无日志。可做两点验证:
- 检查CloudWatch Logs是否存在日志截断情况;
- 通过S3控制台查看文件元数据中的请求ID,如有企业支持计划,可在AWS Support中查询请求异常记录。
3. .promise()与async/await的使用是否有疏漏
代码中await s3.putObject(params).promise()的写法符合aws-sdk v2的规范,没有疏漏。但如果artistsCsv是可读流,存在流未正确关闭导致事件循环未清空的可能——不过文件已上传成功,流应该已被消费完成,可后续转换为Buffer验证。
4. 排查步骤
- 将调用移入Lambda Handler:把异步操作包裹在handler函数内,确保执行流程被Lambda正确管控:
export const handler = async () => { try { await putObjectToS3(artistsCsv, `artists/artists.csv`, 'text/csv'); return { statusCode: 200, body: 'Upload completed' }; } catch (err) { console.error('Handler error:', err); return { statusCode: 500, body: 'Upload failed' }; } }; - 添加错误捕获:在
putObjectToS3中加入try/catch,避免异常被静默吞掉:export async function putObjectToS3( data: any, nameOfFile: string, contentType: string ) { try { const params = { Bucket: process.env.S3_BUCKET || '', ContentType: contentType, Key: `${nameOfFile}`, Body: data }; console.log('start s3 put object'); const response = await s3.putObject(params).promise(); console.log('end s3 put object: ', response); return response; } catch (err) { console.error('S3 upload error:', err); throw err; } } - 调整Lambda超时时间:默认3秒超时可能导致后续日志打印和返回逻辑来不及执行,可暂时延长至10秒测试。
- 验证artistsCsv类型:若
artistsCsv是流对象,转换为Buffer后再上传验证:const buffer = await new Promise((resolve, reject) => { const chunks: Uint8Array[] = []; artistsCsv.on('data', chunk => chunks.push(chunk)); artistsCsv.on('end', () => resolve(Buffer.concat(chunks))); artistsCsv.on('error', reject); }); await putObjectToS3(buffer, `artists/artists.csv`, 'text/csv'); - 检查Lambda执行角色权限:确保角色拥有
logs:CreateLogStream和logs:PutLogEvents权限,避免日志无法写入CloudWatch导致看不到后续输出。
内容的提问来源于stack exchange,提问作者Canovice
相关产品推荐
相关产品推荐

