Lambda 作为泄漏状态机?

Lambda as a leaky state machine?

我有一个涉及 OAuth 1 交互的微服务。我发现自己处于这样一种情况,即具有完全相同起始状态的 Lambda 函数的两个 运行 具有非常不同的结果(其中状态被认为是传入的 "event"、环境变量和 "stageParameters" 来自 API 网关)。

这是一个显示两个背靠背 运行s 的 Cloudwatch 日志:

您可以看到,虽然起始状态相同,但执行路径变化非常快。在第二种情况(失败情况)中,您会看到日志条目 "Auth state changed: null" ...这确实很奇怪,因为实际上这是在 before 甚至第一行代码中记录的的 "handler" 被执行。这是函数处理程序的开头:

export const handler = (event, context, cb) => {
  console.log('EVENT:\n', JSON.stringify(event, null, 2));

那么这个过早的日志条目是从哪里来的呢?好吧,我们必须假设它不知何故是先前处决遗留下来的。让我演示一下……它实际上是一个在先前执行中设置的事件监听器。此函数与 Firebase 数据库交互,第一次连接时会设置以下内容:

auth.signInWithEmailAndPassword(username, password)
  .then((result) => {
    auth.onAuthStateChanged(this.watchAuthState);

其中 watchAuthState 函数很简单:

watchAuthState(user) {
  console.log(`Auth state changed:\n`, JSON.stringify(user, null, 2));
}

这似乎意味着当我第二次 运行 数据库时,我已经 "initialized" 使用了 Firebase 数据库,但显然身份验证已失效。我的首要目标是回到预测状态模型并让它每次都完全相同地执行。

如果有偷偷摸摸的方法以资源有用的方式重用 Lambda 执行之间的缓存状态,那么我想这也会很有趣,但前提是我们可以在实现预测状态机的同时做到这一点。

关于日志顺序,请查看每行开头每个时间戳后的 ID。我相信这是调用 ID。在您用橙色突出显示的两行中,它们来自函数的不同调用。 EVENT 日志是从 ID 以 754ee 结尾的调用中记录的第一行。 Auth state changed: null 行是来自早期函数调用的日志条目,调用 ID 以 c40d5.

结尾

您似乎在调用结束时将 auth 状态设置为 null,但 Firebase 连接是全局的,因此第二次函数调用认为 Firebase 连接已经初始化,但随后它抛出错误,因为身份验证被清零了。

My number one aim is to just get back to a predictive state model and have it execute precisely the same each time.

那么你需要注意Lambda container reuse,不要使用任何全局变量。