AWS Node Lambda 中的变量在调用之间是否存在持续存在的条件?

Jim*_*m J 1 node.js aws-lambda

我不这么认为,但对于我所观察到的情况,我没有其他好的解释。这是相关代码的粗略版本,它位于处理函数内部(即,它不会在调用之间持续存在):

const res = await graphqlClient.query({my query})
const items = res.data.items
console.log(items) // <- this is the line that logs the output below

items.push({id: 'some-id'})
const itemResults = await Promise.all(items.map((item) => etc etc)
Run Code Online (Sandbox Code Playgroud)

在我的客户连续调用(间隔不到十秒)的过程中,some-id被重复添加到items. 第一次调用时,以下是在 CloudWatch 中记录的内容const items = res.data.items

[
  {
    anotherId: 'foo',
    id: 'bar',
  }
]
Run Code Online (Sandbox Code Playgroud)

第二次调用它时,几秒钟后,在调用之前写入日志items.push()

[
  {
    anotherId: 'foo',
    id: 'bar',
  },
  { id: 'some-id' }
]
Run Code Online (Sandbox Code Playgroud)

第三次,在调用之前再次写入日志items.push()

[
  {
    anotherId: 'foo',
    id: 'bar',
  },
  { id: 'some-id' },
  { id: 'some-id' }
]
Run Code Online (Sandbox Code Playgroud)

items永远不会写入持久存储。some-id仅修改两次:当它设置为等于 graphql 查询返回的值时,以及当我手动将另一个值推入堆栈时我可以通过检查是否some-id已在堆栈上来防止此错误,因此我现在已解锁,但它如何在连续运行中持续存在?我从来没想到 Lambda 会有这样的行为!我认为每次调用都是无状态的。

s.h*_*sse 5

AWS Lambda 是一种无状态的,但并不完全是无状态的。你必须小心,这确实是真的。由于上面的示例代码缺少handler function,我假设您没有提供完整的代码并且您已const itemshandler function. 基于我的假设的粗略解释:

  • handler function第一次启动 Lambda 函数(即“冷启动”)时,外部的所有内容都会初始化一次。只要 Lambda 函数的实例保持活动状态,您就可以初始化变量、数据库连接等,并在每次调用中重复使用它们。
  • 然后,您将在初始化步骤之后handler function以及以后的每次调用时被调用。如果您在处理程序函数之外更改值/对象,那么它们将在当前调用中保留下来,并且您可以在下一次调用中使用它们。这样,您可以缓存一些昂贵的数据或进行一些其他优化。例如:
const items = []

exports.handler = function(...) {
  // ...
  items.push(...)
  // ...
}
Run Code Online (Sandbox Code Playgroud)

对于 Java 和 Python Lambda 函数来说也是如此,我相信对于大多数其他运行时也是如此。现在,这可能是对您所观察到的内容的解释:在一次调用中,您正在推送某些内容,items而在下一次调用中,先前的数据仍然存在,因为它存储在处理程序函数之外。

针对您的情况的建议:如果您想要完整的无状态函数,请不要修改处理程序函数之外的数据,而只在内部存储值。但请注意,如果您需要在每次调用中初始化数据,这可能会减慢 Lambda 函数的速度。

由于 AWS Lambda 的这种行为通常用于缓存数据,因此有一些博客文章也涵盖了该主题以及代码如何处理它。他们通常提供更多直观的解释和示例代码:

当然,幕后还发生了更多事情。如果您对整个过程的工作原理感兴趣,我建议您查看执行环境详细信息。本文更侧重于提供构建扩展的背景以及代码外部的流程如何工作,但它可能会帮助您了解幕后发生的情况。