无服务器 Express 应用程序在路由内的逻辑完成之前终止

Serverless express app terminates before logic within route has completed

我有一个简单的 Express 应用程序,托管在 AWS 上,使用无服务器框架。

我正在使用 serverless-http 包装用于部署到 AWS lambda 函数的 express 应用程序,并使用 express-async-await 允许对路由使用异步函数。

对于我的一条路线,我想 return 给用户一个页面,然后继续执行各种异步任务。这是我的代码的缩写版本:

const serverless = require("serverless-http");
const express = require("express");
const mustacheExpress = require("mustache-express");
const aa = require("express-async-await");

// configure our express app
const app = aa(express());
app.use(express.static("static"));
app.engine("html", mustacheExpress());
app.set("view engine", "html");
app.set("views", __dirname + "/views");
app.get("/", async (request, response) => {

  response.render("generating", {  });

  // various async tasks
  await s3.putObject({ });
  await s3.putObject({ });

});

module.exports.handler = serverless(app);

但是,通过检查日志我可以看到 response.render 之后的任务中途停止。 lambda returns 没有错误,没有超时,但任务已停止。

response.render 移动到路由的末尾意味着执行异步任务,但是,用户看到的是旋转器而不是呈现的 HTML 保留页面。

通过四处阅读,我发现许多参考资料表明 Express 非常乐意在响应 returned 后继续执行。

知道我的情况出了什么问题吗?

我会说 AWS lambda 函数在写入响应后终止执行。

¿您是否在 S3 中使用 promises?上传的代码不应该是:

await s3.putObject({ }).promise();

试试看。但是我也建议将 response.render 移动到路线的末尾并处理 front-end 的事情。例如:

// show spinner

// make AJAX request and handle the result asynchronously, for example, assuming you are using axios:
axios.get(url).then(data => {
  // show result to the user
})

// hide spinner and show other HTML while the request finishes

据我所知,Lambda 和 API 网关目前无法使用此用例,因为从 API 网关调用 Lambda 的类型为 RequestResponse,而不是类型 Async

一旦您的代码(在本例中我认为是 serverless-express)调用 context.done(),响应就会从 Lambda 发送到 API 网关和 Lambda 函数的执行上下文已完成(冻结,在下一次调用中 re-used,或回收到 Lambda 的底层基础设施中)。

有几个选项可以调用新函数以继续处理,因此您的 API 可以 return 给用户:

  • 向 SNS 主题发布消息and/or SQS 队列并构建第二个 lambda 来处理消息
  • 使用步进函数
  • 使用AWS-SDK直接调用第二个函数