回到 Node.js 0.10 的原始 Lambda 运行时环境,Lambda 在context
对象中提供了帮助函数:context.done(err, res)
context.succeed(res)
和context.fail(err)
.
这是以前记录的,但已被删除。
使用较早的 Node.js 运行时 v0.10.42是 Lambda 文档中不再存在的页面的存档副本,它解释了如何使用这些方法。
当 Lambda 的 Node.js 4.3 运行时启动时,这些仍然是为了向后兼容(并且仍然可用但未记录),callback(err, res)
并被引入。
这是您的问题的性质,以及为什么您找到的两个解决方案实际上似乎可以解决它。
然而,Context.succeed、context.done 和 context.fail 不仅仅是记账——它们会导致请求在当前任务完成后返回并立即冻结进程,即使其他任务仍保留在 Node.js 事件循环中。如果这些任务代表不完整的回调,通常这不是您想要的。
https://aws.amazon.com/blogs/compute/node-js-4-3-2-runtime-now-available-on-lambda/
因此,使用callback
,Lambda 函数现在以更典型的正确方式运行,但如果您打算在调用之间发生的冻结期间将某些对象保留在事件循环中,这将是一个问题——与旧的(不推荐使用的)done
fail
succeed
方法不同,使用回调不会立即暂停事情。相反,它等待事件循环为空。
context.callbackWaitsForEmptyEventLoop
-- 默认true
-- 被引入,以便您可以将其设置false
为那些您希望 Lambda 函数在您调用回调后立即返回的情况,而不管事件循环中发生了什么。默认值是true
因为可以掩盖函数中的错误,并且如果您没有考虑容器重用的含义,可能会导致非常不稳定/意外的行为——因此,除非并且直到您了解为什么需要它,否则false
您不应将其设置为。false
需要的一个常见原因false
是您的函数建立了数据库连接。如果您在全局变量中创建数据库连接对象,它将有一个打开的套接字,并且可能还有其他东西,如计时器,位于事件循环中。这可以防止回调导致 Lambda 返回响应,直到这些操作也完成或调用超时计时器触发。
确定为什么需要将其设置为false
,如果这是一个正当理由,那么使用它是正确的。
否则,在调用回调时,您的代码可能存在您需要了解和修复的错误,例如使请求处于飞行状态或其他工作未完成。
那么,我们如何解析 Cognito 错误呢?起初,这似乎很不寻常,但现在很明显并非如此。
执行函数时,Lambda 会在配置的秒数后抛出任务超时的错误。当您在 Lambda 控制台中测试您的函数时,您应该会发现这就是发生的情况。
不幸的是,Cognito 在调用 Lambda 函数时似乎采用了内部设计捷径,而不是等待 Lambda 使调用超时(这可能会占用 Cognito 内部的资源)或将其自己的显式计时器强加于 Cognito 将等待的最长持续时间一个 Lambda 响应,它依赖于一个较低层的套接字计时器来限制这个等待......因此在调用超时时会抛出一个“意外”错误。
错误消息的解释更加复杂,错误中缺少引号,其中插入了下层异常。
对我来说,如果错误如下所示,问题会更加清楚:
'arn:aws:lambda:...' failed with error 'Socket timeout' while invoking Lambda function
这种格式将更清楚地表明,当Cognito调用该函数时,它引发了内部Socket timeout
错误(与Lambda遇到意外的内部错误相反,这是我最初的 - 并且不正确的 - 假设)。
Cognito 对 Lambda 函数施加某种响应时间限制是非常合理的,但我没有看到这一点记录在案。我怀疑您的 Lambda 函数本身的短暂超时(使其更快地失败)会导致 Cognito 抛出一个更有用的错误,但在我看来,Cognito 应该被设计为包含逻辑以使其成为预期的、定义的错误,而不是将其归类为“意外”。