在亚马逊lambda上使用mysql池

我正在尝试在Amazon Lambda上运行的NodeJS服务中使用mysql池。 这是我的模块与数据库一起工作的开始:

console.log('init database module ...'); var settings = require('./settings.json'); var mysql = require('mysql'); var pool = mysql.createPool(settings); 

从Amazon控制台中的日志中可以看出,这段代码经常被执行:

  1. 如果我只部署了服务并同时执行了10个请求 – 所有这10个请求都执行这段代码。
  2. 如果我在第一个系列之后立即再次同时执行10个请求 – 他们不执行这个代码。
  3. 如果从最后一个查询中传递了一些时间,那么一些请求将重新执行该代码。

即使我使用全球 – 这减less,但不能消除重复:

 if (!global.pool) { console.log('init database module ...'); var settings = require('./settings.json'); var mysql = require('mysql'); global.pool = mysql.createPool(settings); } 

而且,如果请求执行有一些错误 – 这段代码在请求和global.pool在那个时刻为空之后执行。

那么,这是否意味着在Amazon Lambda中使用池是不可能的? 我有什么select可以让Amazon每次都使用同一个池实例吗?

每次调用Lambda函数时,都会在自己的独立容器中运行。 如果没有闲置的容器可用,则由该服务自动创build新容器。 因此:

  1. 如果我只部署了服务并同时执行了10个请求 – 所有这10个请求都执行这段代码。

如果一个容器可用,它可能很可能会被重用。 当发生这种情况时,进程已经在运行,所以全局部分不再运行 – 调用从处理程序开始。 因此:

  1. 如果我在第一个系列之后立即再次同时执行10个请求 – 他们不执行这个代码。

每次调用完成后,所使用的容器都将被冻结,最终将被解冻并重新用于后续调用,或者如果几分钟后不需要,则会被销毁。 从而:

  1. 如果从最后一个查询中传递了一些时间,那么一些请求将重新执行该代码。

有道理,现在吧?

唯一的“捕捉”是在容器被销毁之前必须经过的时间量不是一个固定值。 有趣的是,它似乎是大约15分钟,但我不相信这是logging,因为最有可能的计时器是适应性的…服务可以(在其分娩)使用启发式预测是否近期活动是一个高峰或可能持续下去,并可能考虑其他因素。

(Lambda @ Edge,Lambda与CloudFront集成,用于HTTP头部处理,似乎以不同的时序运行。闲置容器似乎持续时间更长,至lessless量,但这样做是有道理的,因为它们总是很小的容器。 。这个观察又是一个轶事。)

代码的全局部分仅在创build新容器时运行。

合并是没有意义的,因为在调用过程中没有共享任何东西 – 每次调用是在其容器中运行的唯一一个 – 每个进程一次 – 在任何时间。

但是,您想要做的是更改连接上的idle_timeout 。 MySQL服务器没有一个有效的方法来“发现”一个空闲的连接已经完全消失了,所以当你的连接在容器被销毁的时候消失,服务器就在那里,连接一直保持在Sleep状态,直到默认idle_timeout到期。 默认是28800秒,或者8小时,这个时间太长了。 你可以在服务器上改变它,或者发送查询SET @@IDLE_TIMEOUT = 900 (尽pipe你需要试验一个合适的值)。

或者,您可以build立并销毁每个调用的处理程序内部的连接。 当然,这需要多一点时间,但如果你的function不会经常运行,这是一个明智的方法。 MySQL客户端/服务器协议的连接/握手顺序相当轻巧,频繁的连接/断开连接不会像服务器那样对服务器施加尽可能多的负载……尽pipe您不希望在使用RDS服务器IAM令牌authentication,这是资源密集型的。