【问题标题】:Is there something like Request Scoped in AWS Lambda with node?AWS Lambda 中是否有类似 Request Scoped 之类的东西?
【发布时间】:2018-07-09 14:05:16
【问题描述】:

AWS Lambda(使用 node.js)中是否存在请求安全的范围?这可以是全局可见的,但不会被另一个可能的传入 lambda 事件改变? 例如现在我有这样的东西:

module.exports.handler = (event, context, callback) => {
    dependency.doSomething(event.info)
}

const doSomething = info => {
    anotherLib(info)
}

const anotherLib = info => {
    placeWhereIReallyNeedInfo(info)
}

我想做这样的事情:

module.exports.handler = (event, context, callback) => {
    global.info = event.info
    dependency.doSomething()
}

const doSomething = () => {
    anotherLib()
}

const anotherLib = () => {
    placeWhereIReallyNeedInfo(global.info)
}

但随后另一个 lambda 事件可能会在调用 anotherLib 之前覆盖 global.info。当我有很多不同的文件和异步代码并且需要不断传递函数不需要的参数时,这尤其是一个问题。

提前致谢

【问题讨论】:

    标签: node.js amazon-web-services lambda


    【解决方案1】:

    但随后另一个 lambda 事件可能会在调用 anotherLib 之前覆盖 global.info。

    这实际上不是 Lambda 函数中的问题。按照设计,它永远不会发生。

    永远在每个容器中一次只运行一次函数调用。全局作用域在 Lambda 函数代码中是完全安全的。

    如果一个函数调用正在运行并且另一个函数调用需要启动,那么它总是会毫无例外地在与任何其他当前正在运行的函数完全不同的容器中运行。在第一次调用完全完成之前,容器不会被再次用于函数的另一次调用。

    随着并发性的增加,会自动创建新容器。当一个容器存在几分钟而没有足够的流量来证明它的存在时,它会被服务自动销毁。

    这允许各种感觉有点脏但方便且相当安全的东西,例如创建一个全局“存储”对象而不是传递值。

    当您记得您为每个函数调用支付每 n-gb 毫秒的费用以独占使用运行它的容器时,这是有道理的。

    【讨论】:

    • 谢谢!我测试过,你是对的,全局变量是“安全的”。
    • @Denis,在我看来,有一种可能的情况是您可能会给自己带来问题,那就是如果您设置 context.callbackWaitsForEmptyEventLoop = false,如果您故意这样做是必要的在调用之间的事件循环中保留任何内容,例如与另一个服务的持久 TCP 连接或分叉的孩子。如果您禁用该“等待”设置,并调用最终回调,留下一些未完成的内容,仍在事件循环上运行,那么它当然可能会在下一次调用开始后影响您。但除此之外,答案是准确的。
    • @Michael-sqlbot,可悲的是,经过一些研究,我在这个线程中找到了不同的answer。如果你能用消息来源反驳我的观点,我会很高兴。我真的希望你是对的。
    • @The_Switch 您的答案是正确的,而接受的答案是错误的。如果您没有更改代码并且没有太多时间过去,Lambda 函数可以在同一个容器中重新运行,Lambda 可能会重用以前的容器。您应该避免使用 Lambdas 的状态,因为这是无状态无服务器函数的关键点。 aws.amazon.com/blogs/compute/container-reuse-in-lambda
    • @ericgu 我在这里没有说不同意你刚刚写的东西。我的回答和最初的问题是关于同一容器中的 concurrent 调用,但这不会发生。这个问题和我的回答与维持状态无关。它是关于与并发调用相关的竞争条件的全局范围变量的安全性。
    【解决方案2】:

    在寻找相同答案时,我在 AWS 上找到了以下 Q/A 声明。

    问:AWS Lambda 会复用函数实例吗?

    为了提高性能,AWS Lambda 可能会选择保留您的函数实例并重新使用它来处理后续请求,而不是创建新副本。要了解有关 Lambda 如何重用函数实例的更多信息,请访问我们的文档。您的代码不应假定这种情况总是会发生。

    来源:https://aws.amazon.com/lambda/faqs/

    这让我相信,只要 AWS 的算法认为它应该运行,一个实例就可以继续运行。可能保持全局可用于下一个请求。

    编辑:

    这位科技博主(与我没有任何关系)的测试结果似乎可以证明这一点: https://www.trek10.com/blog/stateless/

    【讨论】:

      【解决方案3】:

      恐怕accepted answer 在这种情况下实际上是错误的。 AWS 将重用函数实例,这意味着全局状态可以从一次调用保留到下一次调用。有关使用 AWS lambda 架构的 encountered in production 的示例,请参阅以下博客文章。

      您应该避免在 lambda 函数中依赖任何可变的全局状态。

      但是,如果您有兴趣探索替代方案,则可以使用 Node 的 Async Hooks API 将状态从一个异步事件传递到另一个异步事件,而无需使用全局变量。我提供了outline code for this approach in a recent blog post

      【讨论】:

      • 恐怕你误解了我的回答,或原来的问题,或两者兼而有之。是的,Lambda 当然会重用容器,但不是同时。在第一个调用仍在运行时开始的第二个调用是当前的主题。 “但是在调用 anotherLib 之前,另一个 lambda 事件可能会覆盖 global.info。” 答案:不,这绝对不会发生。 从一个调用开始到同一个调用结束,全局范围是非常安全的,因为在这个调用结束之前,没有其他调用会触及这个容器。
      • 是的,就像迈克尔的回答更像是我所关心的。我担心在执行过程中会发生变化,这就是我要求 Request Scoped 的原因。如果全局对象在执行后被更改,这对我来说并不重要,因为函数的每次调用只读取它自己写在那里的值。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-03
      • 1970-01-01
      • 2021-09-29
      • 2016-10-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多