使用KNEX和无服务器官方时的连接采集问题
我正在构建
使用网站前端的无服务器应用程序。该网站将查询发送到连接到数据库的API。基础设施托管在AWS上,但我遇到的问题仅影响了本地发展。此设置的一个关键组件是无服务器API,它为每个API路由使用lambdas。为了确保存在与数据库的连接,我将连接到数据库并在执行处理程序执行之前将该连接传递给ORM,并确保完成查询后没有空闲连接,一旦处理程序完成,我就会销毁它们(无论是错误还是优雅)。就实施而言,这些背后的逻辑是合理的。
堆栈
我正在使用无服务器离线插件运行无服务器,以在本地开发节点14应用程序。该数据库是一个Postgres实例,我将其连接到使用反对。在引擎盖下,反对使用KNEX来管理连接,处理查询构建等。
版本
使用的软件版本。
- 节点14
- knex(2.1.0)
- 异议(3.0.1)
- 无服务器(2.55.0)
- 无服务器官能线(8.7.0)
问题
我遇到的问题是连接的,当使用无用的无线电话运行该设置时,我遇到的问题是不可用的。尽管在处理程序的开头连接到数据库,但有时,API查询会引发错误,说明无法获取连接,或者没有数据库可用于查询。这是间歇性发生的,有时相同的API呼叫执行没有任何问题。
我已经意识到,仅当同时执行多个API查询时,这种情况才会发生,尽管并非总是如此。
伪码
在无服务器官能线中的lambda处理程序看起来像这样:
module.exports.handler = async function() {
const connection = await connectToDatabase();
await ORM.databaseConnection.setup(connection);
// ...
const results = ORM.executeQuery();
// ...
await ORM.databaseConnection.destroy();
return results;
}
Setup
I'm building a serverless application that uses a website frontend. The website sends queries to the API, which connects to the database. The infrastructure is hosted on the AWS, but the problem I have ran into only affected the local development. A key component of this setup is the serverless API, which uses Lambdas for each API route. To ensure that connections to the database are present, I connect to the database and pass that connection to the ORM prior to the execution of the handler, and to ensure that no idle connections remain after completing the query, I destroy them once the handler completes (be it with error or gracefully). The logic behind these is sound, as far as implementation goes.
Stack
I am running Serverless with Serverless Offline plugin to develop a Node 14 application locally. The database is a Postgres instance, which I connect to using Objection.JS as ORM. Under the hood, Objection uses Knex to manage the connection, handle query building etc.
Versions
The versions of software used.
- Node 14
- knex (2.1.0)
- objection (3.0.1)
- serverless (2.55.0)
- serverless-offline (8.7.0)
Problem
The problem I have ran into is connections not being available, when running the setup locally using serverless-offline. Despite connecting to the database at the start of the handler, sometimes, the API queries throw an error stating that connection could not be acquired, or that no database is available to a query. This happens intermittently, and sometimes the same API calls execute without any problems.
I have realised that this happens only when multiple API queries are being executed simultaneously, although once again, not always.
Pseudocode
The lambda handler in serverless-offline looks something like this:
module.exports.handler = async function() {
const connection = await connectToDatabase();
await ORM.databaseConnection.setup(connection);
// ...
const results = ORM.executeQuery();
// ...
await ORM.databaseConnection.destroy();
return results;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我花了很长的时间才能最终找到这个问题的来源,这主要是因为它只会偶尔出现(当多个处理程序在本地运行时)。
我已经意识到,这些数据库连接会导致错误的原因(无法获得连接,没有可用的连接以执行查询),是因为Serverless-offers-offline在共享过程中执行Lambda处理程序,这意味着:
由一个lambda函数获取的异议存储的连接。它的连接,这意味着它将没有连接执行对的执行查询。
解决
该问题的解决方案在运行无服务器官能线时,是将Lambda处理程序作为单独的进程运行。这将导致每个处理程序执行在其自己的连接上具有自治权而不会影响其他执行。这可以通过将以下标志添加到无服务器官方命令:
- USECHILDPROCESSES
,例如:It took me an embarasingly long amount of time to finally find the source of this problem, mainly because it would only occur sporadically (when multiple handlers are being ran locally).
I have realised that the reason why these database connections result in errors (not being able to acquire connection, not having available connection to execute query), is because serverless-offline executes the lambda handlers in a shared process, meaning that:
Connection stored by the Objection.JS ORM, acquired by one lambda function, would persist to the other lambda function executing locally at the same time (which is fine), however the moment one of those lambdas destroys its connection, the second lambda would lose its connection, meaning it would have no connection to execute queries against anymore.
Solution
The solution to this problem, when running serverless-offline, is to run the lambda handlers as separate processes. This will result in each handler execution having autonomy over its own connection without affecting other executions. This can be achieved by adding the following flag to the serverless-offline command:
--useChildProcesses
, like so: