AWS Lambda Nodejs 20.x 失败,初始化状态:错误 错误类型:Runtime.Unknown

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

我已将之前工作的 lambda 函数从节点 v18 升级到节点 v20。

在经历了 Nodejs 20 引入的各种问题(一堆看似重大的更改)之后,我终于得到了一个在本地 docker 容器上运行的函数版本。

我使用带有 esm 模块解析的 typescript,后者是 Nodejs 20.x(或多或少)强制执行的(是的,有一个实验性标签解决方法,但我不能依赖它)。

我有一个带有index.ts的项目,转译后变成了index.js。我有所有常见的嫌疑人,如下所示:

project setup

为了确保构建在目标环境中正常运行。我根据镜像设置了Docker:

public.ecr.aws/lambda/nodejs:20

然后我使用 shell 脚本来:

  1. 创建一个 local-dist 目录来复制和更改
    package.json
    以及
    tsconfig.json
    删除对“dist”目录的引用
  2. 在 Dockerfile 中:将这两个文件复制到 /var/task (工作目录)
  3. 在 Dockerfile 中:
    npm install
  4. 在 Dockerfile 中:添加 src 目录并将本地 src 复制到工作目录
  5. 在 Dockerfile 中:
    npm run build

容器具有命令index.handler,因此它应该像原生环境中的Lambda一样运行

一旦经过验证(因为它不会抛出与我的代码相关的错误):

然后我拉出:所有相关文件:

  rm -rf dist
  mkdir dist
  docker cp "$CONTAINER_ID:/var/task/index.js" "dist/index.js"
  docker cp "$CONTAINER_ID:/var/task/index.d.ts" "dist/index.d.ts"
  docker cp "$CONTAINER_ID:/var/task/index.js.map" "dist/index.js.map"
  docker cp "$CONTAINER_ID:/var/task/package.json" "dist/package.json"

  mkdir dist/delegates
  docker cp "$CONTAINER_ID:/var/task/delegates/" "dist/"

  mkdir dist/node_modules
  docker cp "$CONTAINER_ID:/var/task/node_modules/" "dist/"

将它们压缩并发送到 aws lambda:

  pushd dist
    zip -r $LAMBDA_FUNCTION_NAME.zip ./
    aws s3 cp ./$LAMBDA_FUNCTION_NAME.zip $LAMBDA_FUNCTION_BUCKET_URL
  popd

现在这一切显然都有效,因为在 AWS 控制台中我可以看到我的所有代码:

AWS Console: Lambda

在本地看似相同的环境中,我的代码和 AWS lambda 的基本执行脚本可以工作,提供 lambda 函数,但在真正的 Lambda 函数中,我得到了令人难以置信的迟钝、模糊的错误:

2025-01-11T21:12:47.481Z    undefined   ERROR   Uncaught Exception  
{
    "errorType": "Error",
    "errorMessage": "[object Object]",
    "stack": [
        "Error: [object Object]",
        "    at Object.intoError (file:///var/runtime/index.mjs:46:16)",
        "    at Object.textErrorLogger [as logError] (file:///var/runtime/index.mjs:684:56)",
        "    at process.<anonymous> (file:///var/runtime/index.mjs:1272:32)",
        "    at process.emit (node:events:519:28)",
        "    at process._fatalException (node:internal/process/execution:188:25)",
        "    at asyncRunEntryPointWithESMLoader (node:internal/modules/run_main:129:5)"
    ]
}

附带声明:

Phase: init Status: error Error Type: Runtime.Unknown

在 lambda 上(以及在 lambda 的 Docker 版本中),package.json 如下:

{
  "name": "backend",
  "version": "1.0.0",
  "description": "Served by AWS Infrastructure as outlined in [infrastructure](../infrastructure/README.md)",
  "type": "module",
  "main": "index.js",
  "scripts": {
    "build": "tsc",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "Mike Coxon (ZGF)",
  "license": "ISC",
  "devDependencies": {
    "@types/jest": "^29.5.14",
    "jest": "^29.7.0",
    "ts-jest": "^29.2.5",
    "typescript": "^5.7.2"
  },
  "dependencies": {
    "@aws-sdk/client-api-gateway": "^3.699.0",
    "@aws-sdk/client-dynamodb": "^3.699.0",
    "@aws-sdk/client-lambda": "^3.699.0",
    "@aws-sdk/client-s3": "^3.701.0",
    "@aws-sdk/client-ses": "^3.699.0",
    "@aws-sdk/lib-dynamodb": "^3.699.0",
    "@aws-sdk/types": "^3.696.0",
    "@aws-sdk/util-dynamodb": "^3.699.0",
    "@mikeycoxon/aws-lambda-event-http-router": "^0.1.0",
    "@paypal/paypal-js": "^8.1.2",
    "@types/aws-lambda": "^8.10.146",
    "@types/node": "^22.10.1",
    "@types/uuid": "^10.0.0",
    "aws-jwt-verify": "^4.0.1",
    "http-status-codes": "^2.3.0",
    "uuid": "^11.0.3"
  }
}

有人知道这里发生了什么吗? 这个东西在节点 18 上工作。

或者至少,我可以尝试从 AWS 的 lambda 执行环境中获取更多信息吗?

提前致谢。

编辑

我回去查看了之前的工作实现,并意识到我之前正在转换为通用 JS(当使用节点 18 时)。所以这可能很重要。

编辑2

好的,我知道发生了什么,但根据 AWS doco,我不知道为什么会发生。

本质上,尽管定义了环境变量......

process.env.<ANYTHING>
始终未定义 Node 18.x 下并非如此

事实证明,从 Node 20.6 开始,启用了对 ENV 变量的本机支持(不再需要 dotenv 和等效项)。

结果似乎是使用外部环境变量配置 lambda 不再起作用!

也许 Node 20.6 破坏了 lambdas process.env 解析?

所以我决定按照节点 doco 的建议提供我自己的 .env 文件:

lambda console with .env

你猜怎么着! - 有点远了

INIT_REPORT Init Duration: 3013.19 ms  Phase: invoke   Status: timeout

为什么超时?我的意思是,这不是一个很大的项目。可能现阶段对环境变量的支持有点理论化?除非有其他原因导致超时。

天哪,我在想……回到 Node 18x :(

编辑3

将控制台的超时时间增加到10秒,但该功能在3秒后初始化时仍然超时。

远方。我需要一些 AWS 专家来告诉我发生了什么事。

node.js aws-lambda es6-modules node.js-v20
1个回答
0
投票

已解决

如果您查看两个 lamda 函数控制台图像中的第一个,您可以看到处理程序声明写为:

exports.handler = async (event: APIGatewayProxyEvent) => {
...
}

这当然是一个 commonjs 声明,它应该围绕“无导出模块”(在 ESM 的上下文中)引发致命异常。但 AWS Lambda 的 UserFunction.mjs 似乎掩盖了这一点并启动了一个损坏的实例,该实例响应请求,但不以任何方式附加或引用(解释了为什么更改超时值没有效果)。

我将上面的内容更改为:

export const handler: Handler = async (event: APIGatewayProxyEvent) => {
...
}

瞧!一切突然变得美好起来。

在尝试解决此问题的过程中,我将环境变量硬编码到应用程序中,因此我没有回去测试其中任何一个是否按广告那样工作。经过两天半的撕扯我的头发后,我实在不想再打扰了。

请所有 AWS Node Lambda 开发人员注意:如果找不到导出的用户函数,请不要隐藏异常,只需抛出它即可。无论如何,它永远不会起作用,而您所做的只是向开发人员隐藏问题的真正原因,隐藏在我认为我遇到过的最迟钝的错误消息之一之后,即:

Status: error Error Type: Runtime.Unknown

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