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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 19:27:07