Bor*_*ris 3 node.js aws-lambda
我正在尝试在我的运行在Amazon Lambda上的NodeJS服务中使用mysql池.这是我的模块的开始,它与数据库一起使用:
console.log('init database module ...');
var settings = require('./settings.json');
var mysql = require('mysql');
var pool = mysql.createPool(settings);
Run Code Online (Sandbox Code Playgroud)
如下面的亚马逊控制台中的日志,这段代码经常执行:
即使我使用全局 - 这会减少但不会消除重复:
if (!global.pool) {
console.log('init database module ...');
var settings = require('./settings.json');
var mysql = require('mysql');
global.pool = mysql.createPool(settings);
}
Run Code Online (Sandbox Code Playgroud)
此外,如果请求执行有一些错误 - 这段代码在请求之后执行,而global.pool在那时为空.
那么,这是否意味着在Amazon Lambda中使用池是不可能的?有什么选择我怎么能让亚马逊每次都使用相同的池实例?
每次调用Lambda函数时,它都在自己的独立容器中运行.如果没有可用的空闲容器,则服务会自动创建一个新容器.因此:
- 如果我只是部署了服务并同时执行了10个请求 - 所有这10个请求都执行这段代码.
如果容器可用,它可能并且很可能会被重用.当发生这种情况时,进程已经在运行,因此全局部分不会再次运行 - 调用从处理程序开始.因此:
- 如果我在第一次系列之后立即再次同时执行10个请求 - 它们不会执行此代码.
每次调用完成后,使用的容器将被冻结,最终将被解冻并重新用于后续调用,或者如果在几分钟后不需要,则会被销毁.从而:
- 如果从最后一个查询传递了一些时间 - 那么一些请求会重新执行该代码.
现在有道理,对吧?
唯一的"问题"是在销毁容器之前必须经过的时间量不是固定值.有趣的是,它似乎是大约15分钟,但我不相信它是有记录的,因为很可能计时器是自适应的...服务可以(在它的自由裁量权时)使用启发式方法来预测最近的活动是否是尖峰或可能是持续,并可能考虑其他因素.
(Lambda @ Edge,它是与CloudFront集成的Lambda用于HTTP标头操作,似乎在不同的时间运行.空闲容器似乎持续更长时间,至少是少量,但这是有道理的,因为它们总是非常小的容器..而且这个观察结果再次轶事.)
代码的全局部分仅在创建新容器时运行.
池化没有意义,因为在调用期间没有任何共享 - 每次调用都是在其容器中运行的唯一调用 - 每个进程一次 - 在任何时候.
但是,您要做的是改变idle_timeout连接.MySQL服务器没有一种有效的方法来"发现"空闲连接完全消失,所以当容器被破坏时你的连接消失,服务器只是坐在那里,连接保持在Sleep状态,直到默认idle_timeout到期.默认值为28800秒,或8小时,这太长了.您可以在服务器上更改此设置,也可以发送查询SET @@IDLE_TIMEOUT = 900(尽管您需要尝试使用适当的值).
或者,您可以为每次调用建立和销毁处理程序内部的连接.当然,这会花费更多的时间,但如果你的功能不会经常运行,这是一种明智的方法.MySQL客户端/服务器协议的连接/握手序列相当轻量级,并且频繁的连接/断开不会对服务器造成如您所料的那样多的负载......尽管您不希望在使用的RDS服务器上执行此操作IAM令牌身份验证,这是更加资源密集型的.