我已将之前工作的 lambda 函数从节点 v18 升级到节点 v20。
在经历了 Nodejs 20 引入的各种问题(一堆看似重大的更改)之后,我终于得到了一个在本地 docker 容器上运行的函数版本。
我使用带有 esm 模块解析的 typescript,后者是 Nodejs 20.x(或多或少)强制执行的(是的,有一个实验性标签解决方法,但我不能依赖它)。
我有一个带有index.ts的项目,转译后变成了index.js。我有所有常见的嫌疑人,如下所示:
为了确保构建在目标环境中正常运行。我根据镜像设置了Docker:
public.ecr.aws/lambda/nodejs:20
然后我使用 shell 脚本来:
package.json
以及
tsconfig.json
删除对“dist”目录的引用npm install
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 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 文件:
你猜怎么着! - 有点远了
INIT_REPORT Init Duration: 3013.19 ms Phase: invoke Status: timeout
为什么超时?我的意思是,这不是一个很大的项目。可能现阶段对环境变量的支持有点理论化?除非有其他原因导致超时。
天哪,我在想……回到 Node 18x :(
编辑3
将控制台的超时时间增加到10秒,但该功能在3秒后初始化时仍然超时。
远方。我需要一些 AWS 专家来告诉我发生了什么事。
已解决
如果您查看两个 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