Bug 报告:Python Lambda 环境隔离的失败?

0

【以下的问题经过翻译处理】 我在 python 3.6 lambda 中实现了单例设计模式,发现之前的 lambda 执行影响了当前的执行。具体来说,单例类的实例在多个 lambda 环境中是相同的。我很好奇这些对于如何隔离 python lambda 意味着什么?

我遵循了这个流行的堆栈溢出帖子的“方法 3”中描述的单例实现:https://stackoverflow.com/questions/6760685/creating-a-singleton-in-python

这是一个例子。

lambda代码:

import json

class Singleton(type): _instances = {}

def __call__(cls, *args, **kwargs):  
    if cls not in cls._instances:  
        cls._instances\[cls] = super(Singleton, cls).__call__(*args, **kwargs)  
    return cls._instances\[cls]
  

class Foo(metaclass=Singleton): def init(self): self.bar = [] print(f"'bar' attribute is {self.bar}")

def lambda_handler(event, context):

foo = Foo()  
  
print(f"after instantiating 'foo', bar attribute is {foo.bar}")  
foo.bar.append(0)  
print(f"after append, bar attribute is {foo.bar}")

连续多次手动触发 lamba 后产生的 Cloudwatch 日志。我相信新实例没有在第一个之后的 lambda 中实例化,因为“bar”属性包含来自前一个 lambda 的数据。


01:57:14 START RequestId: 69e78a31-4a5e-4e84-abd9-44108f390838 Version: $LATEST 01:57:14 'bar' attribute is [] 01:57:14 after instantiating 'foo', bar attribute is [] 01:57:14 after append, bar attribute is [0] 01:57:14 END RequestId: 69e78a31-4a5e-4e84-abd9-44108f390838 01:57:14 REPORT RequestId: 69e78a31-4a5e-4e84-abd9-44108f390838 Duration: 1.49 ms Billed Duration: 100 ms Memory Size: 128 MB Max Memory Used: 56 MB Init Duration: 114.96 ms 01:57:21 START RequestId: adacf02b-39b8-468e-a7a5-f4c09bda5758 Version: $LATEST 01:57:21 after instantiating 'foo', bar attribute is [0] 01:57:21 after append, bar attribute is [0, 0] 01:57:21 END RequestId: adacf02b-39b8-468e-a7a5-f4c09bda5758 01:57:21 REPORT RequestId: adacf02b-39b8-468e-a7a5-f4c09bda5758 Duration: 1.38 ms Billed Duration: 100 ms Memory Size: 128 MB Max Memory Used: 56 MB 01:57:22 START RequestId: d66468cd-f09d-4c28-9343-0eeb52b316e9 Version: $LATEST 01:57:22 after instantiating 'foo', bar attribute is [0, 0] 01:57:22 after append, bar attribute is [0, 0, 0] 01:57:22 END RequestId: d66468cd-f09d-4c28-9343-0eeb52b316e9 01:57:22 REPORT RequestId: d66468cd-f09d-4c28-9343-0eeb52b316e9 Duration: 1.62 ms Billed Duration: 100 ms Memory Size: 128 MB Max Memory Used: 56 MB 01:57:23 START RequestId: 89813b23-9cb1-4284-ab11-472b84151666 Version: $LATEST 01:57:23 after instantiating 'foo', bar attribute is [0, 0, 0] 01:57:23 after append, bar attribute is [0, 0, 0, 0] 01:57:23 END RequestId: 89813b23-9cb1-4284-ab11-472b84151666 01:57:23 REPORT RequestId: 89813b23-9cb1-4284-ab11-472b84151666 Duration: 1.39 ms Billed Duration: 100 ms Memory Size: 128 MB Max Memory Used: 56 MB


profile picture
专家
已提问 4 个月前24 查看次数
1 回答
0

【以下的回答经过翻译处理】 嗨 Lookatthisgraph,

看起来你正在尝试使用Lambda运行时环境!

== 一个简短的答案以及为什么这不是一个错误而是一个特性 ==

根据强大的互联网:

可能最简单的设计模式是单例模式,它是一种提供特定类型的一个且仅一个对象的方式...... https://python-3-patterns-idioms-test.readthedocs.io/en/latest/Singleton.html

并且由于你是在句柄之外创建的,还根据以下文章(它使用node作为示例,但此行为在不同运行时中相同):

在被创建或代码或资源配置更新后首次执行函数时,将创建一个具有适当资源的新容器来执行它,并将函数代码加载到容器中。在nodejs中,初始化代码在首次调用处理程序之前每次容器创建时都会执行一次。 https://aws.amazon.com/blogs/compute/container-reuse-in-lambda/

因此,这是Lambda容器的正常行为,并且事实上,我们的许多客户积极利用了这个特性。

== 如何使用这个特性 ==

因此,从最佳实践中可以得出以下结论:

利用执行环境重用来提高函数的性能。在函数处理程序之外初始化SDK客户端和数据库连接,并将静态资产缓存在/tmp目录中。由同一实例处理的后续调用可以重用这些资源。这可以节省执行时间和成本。 为避免跨调用的潜在数据泄漏,请勿使用执行环境存储用户数据、事件或具有安全影响的其他信息。如果您的函数依赖于无法在处理程序内存储的可变状态,请考虑为每个用户创建单独的函数或单独

profile picture
专家
已回答 4 个月前

您未登录。 登录 发布回答。

一个好的回答可以清楚地解答问题和提供建设性反馈,并能促进提问者的职业发展。

回答问题的准则