我有一个托管在 Amazon Linux AMI 上的应用程序后端,它是我大约 6 个月前设置的。最初,我没有太多考虑就使用了 Node.js 17.x,因为它是我的 AWS AMI 设置的一部分。
但是,我注意到一个反复出现的问题:每次活动长时间中断时,任何数据库查询调用(包括 SELECT 语句)都会导致 Knex 超时错误:
Knex: Timeout acquiring a connection. The pool is probably full. Are you missing a .transacting(trx) call?
奇怪的是,在连续第二次调用时,查询执行成功。
经过研究,我发现这是一个众所周知的问题(Knex:获取连接超时。池可能已满。你是否错过了 .transacting(trx) 调用?),人们已经设法解决了它通过修复 Objection/Knex 版本或调整其 Node.js 版本。
最初,我尝试通过升级到来修复它:
"knex": "^3.1.0",
"objection": "^3.1.4"
但是在这个过程中我遇到了来自Objection和Knex的警告,问题依然存在。最终,我通过使用 NVM 降级到 Node.js v12.22.12 (Erbium) 成功解决了这个问题。
虽然到目前为止我还没有遇到这个旧 Node.js 版本的任何问题,但我不确定它是否是长期可持续的解决方案。我也不确定是否有任何我忽略的 Knex/Objection 配置调整。
这是我当前的生产配置:
{
client: "postgresql",
connection: {
host: "<host>",
database: "<dbname>",
user: "<user>",
password: "<password>"
},
pool: {
min: 2,
max: 10
},
migrations: {
tableName: "knex_migrations"
}
}
总结:
提前致谢!
问题实际上在于 knex 的连接池处理程序 - tarn。 tarn 有一个已知的错误,它无法正确处理您试图保持活动状态的连接(最小数量)。它们没有被正确回收。我不知道完整的技术细节,但是我遇到了同样的问题,解决方案是将
pool.min
值设置为 0
,因为这样可以正确关闭它们并且不会开始秘密收集它们。平均而言,您预期的“超时”错误会在未向 knex 实例发出请求后 5-15 分钟内发生。因此,如果您想测试设置min = 0
,那么您应该等待 15 分钟以上,看看该行为是否消失。
其他帖子中提出的替代解决方案,如下所示:Knex:获取连接超时。泳池可能已经满了。您是否错过了 .transacting(trx) 调用?,建议使用
propogateError
选项,但是 knex 团队强烈反对它,尽管您可以利用我对它不够熟悉,无法说出预期的行为。
我强烈建议不要通过降级 Node 实例来解决此问题