NodeJS 从 AWS Lambda 函数流出

问题描述 投票:0回答:3

我们正在尝试将 zip 微服务从 Nodejs Express 中的常规应用程序迁移到与 AWS Lambda 集成的 AWS API Gateway。
我们当前的应用程序向我们的 API 发送请求,获取附件列表,然后访问这些附件并将其内容以 zip 存档的形式返回给用户。它看起来像这样:

module.exports = function requestHandler(req, res) {

  //...
  //irrelevant code
  //...

  return getFileList(params, token).then(function(fileList) {
    const filename = `attachments_${params.id}`;
    res.set('Content-Disposition', `attachment; filename=${filename}.zip`);

    streamFiles(fileList, filename).pipe(res); <-- here magic happens
  }, function(error) {
    errors[error](req, res);
  });
};

除了必须从 Lambda 函数流式传输内容的部分之外,我已成功完成所有操作。
我认为可能的解决方案之一是使用 aws-serverless-express,但我想要一个更优雅的解决方案。

有人有什么想法吗?是否有可能从 Lambda 中流出?

node.js amazon-web-services express aws-lambda
3个回答
15
投票

不幸的是,lambda 不支持流作为事件返回值。 (很难在文档中找到明确提及的内容,除非注意工作文档中如何描述调用和上下文/回调)。

在您的示例中,您必须等待

streamFiles
,然后返回完成的结果。

aws-serverless-express
在这里没有帮助,如果您检查代码,他们会等待管道完成后再返回:https://github.com/awslabs/aws-serverless-express/blob/master/src/index.html js#L68

n.b.这里有一个细微差别,许多语言 SDK 支持流式传输请求/响应,但这意味着连接到流传输,例如从 lambda 下载完整响应的流,而不是侦听从 lambda 发出的流。


0
投票

遇到了同样的问题,现在确定如何直接通过本机 lambda + API 网关进行流/管道...但在技术上是可行的。

我们使用了

Serverless Framework
并且能够通过此入门套件使用
XX.pipe(res)
(https://github.com/serverless/examples/tree/v3/aws-node-express-dynamodb-api)

有趣的是,这只是包装了本机 lambda + API 网关,因此从技术上讲这是可能的,因为他们已经做到了。

祝你好运


0
投票

自 2023 年 4 月起,可以从 NodeJS Lambda 函数流式传输结果(请参阅:introducing-aws-lambda-response-streaming)。

但是,请记住,此处不支持开箱即用地使用 API 网关作为函数的入口点。如果您想扩展调用,您将需要使用 HTTP 代理或创建 CloudFront 发行版。

API Gateway 和 Lambda 与 Application Load Balancer 的目标集成都不支持分块传输编码。因此,它不支持更快的 TTFB 流式响应。但是,您可以将响应流与 API Gateway 结合使用来返回更大的负载响应,最高可达 API Gateway 的 10 MB 限制。要实现此目的,您必须在 API 网关和 Lambda 函数 URL 之间配置 HTTP_PROXY 集成,而不是使用 LAMBDA_PROXY 集成。

您可以通过设置一个简单的处理程序来进行测试,如下所示:

exports.handler = awslambda.streamifyResponse(async (event, responseStream, context) => {
    responseStream.setContentType("text/plain");
    
    for (let i = 0; i < 5; i++) {
        responseStream.write(`Message ${i}\n`);
        await new Promise(resolve => setTimeout(resolve, 1000));
    }
    responseStream.end();
});

然后通过函数 URL 调用该函数并观察消息流。

© www.soinside.com 2019 - 2024. All rights reserved.