【问题标题】:AWS http api gateway + lambda (node/express) Internal Server ErrorAWS http api gateway + lambda (node/express) 内部服务器错误
【发布时间】:2023-02-16 17:11:55
【问题描述】:

当我有一个长时间运行的查询时,我得到 internal server error。 实际上,我必须通过 API 获取历史数据,有时可能需要超过 30 秒的时间。这取决于查询的复杂程度。也可能需要 1 分钟。

不确定但猜测,API 网关超时设置为 30 秒(我不能增加它)并且我的查询执行时间超过 30 秒。所以我得到internal server error我相信。

我怎么能说上面的陈述?

因为如果我在本地运行相同的查询,我的意思是通过运行 npm run start 在本地节点/express 中运行,即使需要 1 分钟,它也能正常工作,响应总是会回来。

但是当我部署节点/快递lambda 函数的代码,如果任何查询需要更长的执行时间,它就会抛出错误。

我有以下节点/快递设置

const express = require("express");
const serverless = require("serverless-http");
const app = express();

app.use(cors());
app.use((req, res, next) => {
    res.setHeader('Connection', 'keep-alive');                   // I added this line as suggested in some post but not helping
    res.setHeader('Keep-Alive', 'timeout=30');                   // I added this line as suggested in some post but not helping
    res.setHeader("Access-Control-Allow-Headers", "X-Requested-With,content-type");
    res.setHeader("Access-Control-Allow-Origin", "*");
    res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS, PUT, PATCH, DELETE");
    res.setHeader("Access-Control-Allow-Credentials", true);
    next();
});

app.use(express.json());
app.use(express.urlencoded({ extended: true }));

app.use(`api-end-point/user`, userRoute);
....

if (process.env.NODE_ENV !== "lambda") {

    PORT = process.env.PORT || 7000;
    const server = app.listen(PORT, () => {
        console.log(`node-express server running in ${process.env.NODE_ENV} mode on ${PORT}`);
    });
    server.timeout = 0;

}else {

    module.exports.handler = serverless(app);     // this is for lambda function

}

我将此代码部署到 AWS lambda 函数。


HTTP API网关配置了两条路由/ANY, /{proxy+}


暂停

API网关设置为默认值 30 seconds。[我不能增加这个时间,因为 AWS 不允许]

拉姆达设置为10 **mins**


CORS


我真的不知道该如何解决这个问题?

如何增加 API 网关超时或如何使连接保持活动状态?

【问题讨论】:

  • Bdw 我认为您还可以查看与 lambda 函数关联的 cloudwatch 日志,以查看它占用了多少或任何其他内部服务器错误。

标签: node.js amazon-web-services express aws-lambda aws-api-gateway


【解决方案1】:

您不能将 API 网关超时增加到大于 30 秒,如前所述。

目前我知道的唯一解决方案是异步运行 Lambda,但这不能在 Http API 中完成。但是,如果您愿意将其更改为 REST API,那么这可以通过在 REST API 中打开 Lambda 代理集成和使用调用标头 X-Amz-Invocation-Type 异步调用 Lambda 的组合来完成。这将允许您的 Lambda 通过 API 调用异步运行(最多 15 分钟)。

【讨论】:

  • 不幸的是,我无法将其更改为 Rest API。我不得不忍受 HTTP API。
  • @micronyks 另一种选择是使用您的 HTTP API 调用您在 Fargate 中运行的任务定义过程。创建一个由 API 调用调用的任务定义,并在它临时启动的 ECS 容器中运行您的处理代码。
  • 我不是 AWS 专家。我只有一些基础知识。任何链接或进一步的指导都有助于理解您的评论。
  • @micronyks 你必须做一些谷歌搜索;您需要了解如何使用 Docker 创建容器,将代码加载到该容器中,将该容器推送到 AWS 中的弹性容器注册表 (ECR),然后定义任务以在弹性容器服务 (ECS) 中运行该容器),然后通过 API 调用触发它。
【解决方案2】:

https://docs.aws.amazon.com/apigateway/latest/developerguide/limits.html

由于无法增加超时,您可以使用单个 HTTP 请求更改为

  1. 客户端POST查询
  2. 服务器响应结果的 url
  3. 客户端多次获取 url -- 结果准备好时它将是 200 OK
    • 或 WebSocket

    文档说 WebSocket 的 Idle Connection Timeout 最多 10 分钟

【讨论】:

  • 怎么做 ?我只为所有端点配置了一条路由。怎么做?
【解决方案3】:

使用 Lambda 意味着订阅无服务器目录/哲学中的模式。这意味着尽可能使用异步。

据我了解,您的 Lambda 需要收到一个请求,然后再调用某个东西(未指定),这需要 30~60 秒。

API 网关的硬编码超时为 29 秒(硬限制)。

要解决这个问题,应用程序需要重新架构:

  • 使用前端的 X-Amz-Invocation-Type Event 异步触发 Lambda。
  • Lambda 调用历史 API 并将结果存储在某些存储(DynamoDB、S3、RDS 等)中。
  • 前端从前端查询后端直到数据可用(或使用WebSockets)

这样,历史 API 调用最多可以占用 15m,并且可以将调用缓存在存储中以加快进一步调用的速度。如果它需要超过 15m,那么我会要求历史 API 重新架构。

【讨论】:

    猜你喜欢
    • 2019-12-21
    • 2019-10-26
    • 2019-12-10
    • 2021-02-04
    • 1970-01-01
    • 1970-01-01
    • 2020-04-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多