ALB-Lambda-S3架构下Lambda返回S3文件响应失败排查
问题分析与解决方案
核心问题:S3对象Body处理逻辑错误
AWS SDK v3中,GetObjectCommand返回的data.Body是Node.js ReadableStream,并非字符串或Buffer类型,直接调用toString('base64')会触发错误——因为ReadableStream没有该方法。这是Lambda无法生成有效响应、最终导致ALB返回504超时的主要原因。
修复步骤
1. 正确转换S3对象Body为Base64
需要先将ReadableStream读取为Buffer,再转换为Base64字符串,以下是两种可行实现:
方式一:使用stream/promises(推荐Node.js 16+)
import { GetObjectCommand, S3Client } from "@aws-sdk/client-s3"; import { pipeline } from "stream/promises"; import { Buffer } from "buffer"; const s3 = new S3Client({region: 'ap-southeast-2'}); export const handler = async (event) => { const path = event.path; if (path === "/lp/test.pdf") { const command = new GetObjectCommand({ Bucket: 'test-bucket', Key: 'lp/test.pdf' }); try { const data = await s3.send(command); const chunks = []; // 读取流数据到缓冲区 await pipeline(data.Body, async function*(source) { for await (const chunk of source) { chunks.push(chunk); } }); const buffer = Buffer.concat(chunks); const response = { statusCode: 200, headers: { 'Content-Type': 'application/pdf', }, body: buffer.toString('base64'), isBase64Encoded: true, }; return response; } catch (error) { console.error('Error:', error); return { statusCode: 500, body: JSON.stringify({message: error.message}), }; } } else { return { statusCode: 404, body: JSON.stringify({message: 'Path not found'}), }; } };
方式二:使用util.promisify(兼容旧版Node.js)
import { GetObjectCommand, S3Client } from "@aws-sdk/client-s3"; import { promisify } from "util"; import { pipeline } from "stream"; import { Buffer } from "buffer"; const s3 = new S3Client({region: 'ap-southeast-2'}); const pipelineAsync = promisify(pipeline); export const handler = async (event) => { const path = event.path; if (path === "/lp/test.pdf") { const command = new GetObjectCommand({ Bucket: 'test-bucket', Key: 'lp/test.pdf' }); try { const data = await s3.send(command); const chunks = []; await pipelineAsync( data.Body, (chunk) => chunks.push(chunk) ); const buffer = Buffer.concat(chunks); const response = { statusCode: 200, headers: { 'Content-Type': 'application/pdf', }, body: buffer.toString('base64'), isBase64Encoded: true, }; return response; } catch (error) { console.error('Error:', error); return { statusCode: 500, body: JSON.stringify({message: error.message}), }; } } else { return { statusCode: 404, body: JSON.stringify({message: 'Path not found'}), }; } };
2. 补充边缘场景处理
- 路径不匹配时返回明确的404响应,避免Lambda无返回导致ALB超时
- 错误捕获时返回简洁的错误信息,便于快速定位问题
3. ALB排查方向(修复后仍出现504时)
- 检查ALB空闲超时时间:默认60秒,若Lambda处理大文件耗时超过此值,需调整ALB超时配置或优化Lambda性能
- 确认ALB与Lambda的集成配置:确保目标组类型为Lambda,触发规则匹配请求路径
- 查看Lambda执行日志:检查是否存在未捕获异常或执行超时(Lambda默认超时3秒,可按需调整)
内容的提问来源于stack exchange,提问作者oshigoto46
相关产品推荐
相关产品推荐

