来自AWS Lambda的MongoDB连接
我正在使用连接到MongoDB数据库的AWS Lambda / API网关创build一个RESTful API。 我读过与MongoDB的连接是相对昂贵的,所以最好的做法是在build立连接后保留一个连接,而不是为每个新的查询build立新的连接。
对于正常的应用程序来说,这非常简单,因为您可以在启动期间build立连接,并在应用程序生命周期中重新使用它。 但是,由于Lambda被devise为无状态,因此保持这种联系似乎不那么简单。
因此,我想知道什么是解决这个数据库连接问题的最好方法? 我每次调用Lambda函数时都被迫创build新的连接,还是有办法对这些连接进行缓冲/caching以获得更高效的查询?
谢谢。
AWS Lambda函数应该定义为无状态函数,因此它们不能像连接池那样保持状态。
在这个AWS论坛post中也提到了这个问题 。 2015年10月5日,AWS工程师Sean表示,不应该在每个请求上打开和closures连接,通过在代码初始化时在处理程序块之外创build一个池。 但两天后,同一个工程师发布, 你不应该这样做 。
问题是您无法控制Lambda的运行时环境。 我们知道,这些环境(或容器)被重复使用,正如Tim Wagner所描述的博客文章所描述的那样。 但缺乏控制可能会导致您耗尽所有资源,如达到数据库中的连接限制。 但这取决于你。
您可以使用RESTHeart通过HTTP访问数据库,而不是从您的lambda函数连接到MongoDB。 到MongoDB的连接池由RESTHeart维护。 请记住,关于性能,您将在每个请求上打开一个到RESTHeart的新HTTP连接,而不是像使用传统应用程序那样使用HTTP连接池。
Restheart是一个与MongoDB一起运行的基于REST的服务器。 它将Mongo中的大多数CRUD操作映射到GET,POST等等,当您需要编写自定义处理程序(例如,专门的geoNear,geoSearch查询)时,具有可扩展支持的请求,
我运行了一些执行连接到MongoDB Atlas的Java Lambda函数的testing。
正如其他海报已经说过,亚马逊不会重复使用这些实例,但是这些实例可能会被回收,并且确切的行为无法确定。 所以人们可能会失去联系。 我每5分钟收集一次数据,并每5分钟将其推送到Lambda函数。
Lambda基本上是这样做的:
- build立或重用连接
- 查询一条logging
- 写或更新一个logging
- closures连接或将其打开
实际的数据量非常低。 取决于一天的时间,它从1到5 kB不等。 我只用了128 MB。
Lambdas在N.Virgina跑了,因为这是免费级别的地方。
每次打开和closures连接时,大多数呼叫需要4500 – 9000毫秒。 重新使用连接时,大多数呼叫在300 – 900毫秒之间。 检查Atlas控制台连接计数保持稳定。 对于这种情况重用连接是值得的。 使用Java驱动程序build立连接,甚至是从副本集断开连接都相当昂贵。
对于大规模部署,应该运行更全面的testing。
你应该认为lambda是无状态的,但实际情况是大多数时候vm只是被冻结, 并且保持某种状态。 对于亚马逊来说,为每一个请求启动一个新的进程将是愚蠢的,所以他们经常重复使用相同的过程,你可以利用这个来避免连接的颠簸。
为了避免连接每个请求(在lambda进程被重用的情况下):
-
编写处理程序,假定重新使用该进程,以便连接到数据库并让lamba重用连接池(从
MongoClient.connect
返回的db
承诺)。 -
为了让lambda不会等待你closures数据库连接,
db.close()
,在服务请求之后告诉它不要等待一个空的事件循环。
例:
var db = MongoClient.connect(MongoURI); module.exports.targetingSpec = (event, context, callback) => { context.callbackWaitsForEmptyEventLoop = false; db.then((db) => { // use db }); };
从关于context.callbackWaitsForEmptyEventLoop
的文档中:
callbackWaitsForEmptyEventLoop默认值为true。 此属性仅用于修改callback的默认行为。 默认情况下,callback将等待,直到Node.js运行时事件循环为空,然后冻结进程并将结果返回给调用者。 您可以将此属性设置为false以请求AWS Lambda在调用callback后立即冻结该进程,即使事件循环中有事件。 AWS Lambda将冻结进程,Node.js事件循环中的任何状态数据和事件(下一次调用Lambda函数时处理事件循环中的任何剩余事件,以及AWS Lambdaselect使用冻结进程)。 有关callback的更多信息,请参阅使用callback参数。
不幸的是,您可能需要创build自己的RESTful API来回答MongoDB请求,直到AWS出现一个请求。 到目前为止,他们只有自己的Dynamo DB需要的东西。
除了保存连接以供重用外,还要增加lambda函数的内存分配。 AWS根据内存分配按比例分配CPU,当从128MB变为1.5Gb时,连接时间从4秒下降到0.5秒,连接到mongodb地图集。
阅读更多信息: https : //aws.amazon.com/lambda/faqs/
我前几次面对同样的问题,但我已经决定把我的mongo放在EC2的账户上。 我在我的lambda函数所在的同一AWS EC2帐户上创build了一个mongo数据库。
现在我可以使用私有IP从lambda函数访问我的mongo。