如何在 RDS 上正确使用 Knex / Bookshelf 和 MySQL

Posted

技术标签:

【中文标题】如何在 RDS 上正确使用 Knex / Bookshelf 和 MySQL【英文标题】:How to properly use Knex / Bookshelf with MySQL on RDS 【发布时间】:2020-03-15 02:25:55 【问题描述】:

我有一个Node.js 应用程序,在AWS RDS 上使用mysqlBookshelfKnex 库。 RDS 实例有一个max_connections90。 我使用以下作为连接对象。

knex: 
  client: 'mysql',
    connection: 
      host: 'xxxxxxx.rds.amazonaws.com',
      user: 'xxx',
      password: 'xxxxx',
      database: 'xxxx',
      charset: 'utf8'
  ,
  debug: true,
  pool: 
    min: 2,
    max: 20
  ,
  acquireConnectionTimeout: 10000
,
const config = require('./environment');
const knex = require('knex')(config.knex);
module.exports = require('bookshelf')(knex).plugin('registry');
'use strict';

const bookshelf = require('../config/bookshelf');
const config = require('../config/environment');
module.exports = bookshelf.model(`TableA`, 
    tableName: 'TableA'
, );

我的应用程序收到了许多请求,有时会因以下错误而崩溃。

未处理的拒绝 TimeoutError: Knex: Timeout getting a 联系。游泳池可能已经满了。你错过了一个 .transacting(trx) 调用?

错误:ER_CON_COUNT_ERROR:连接太多

我还看到服务器 PROCESSLIST 中有许多连接(平均为 40 到 50 个),Commandsleep

我怀疑这些错误发生在服务器上的所有90 连接已完全使用/knex 尝试从池中获取新连接时。什么可能是解决此问题的永久解决方案,以及处理此类应用程序的最佳实践。

【问题讨论】:

可能值得提供有关创建和使用数据库连接的代码摘录。 更新了@RichChurcher,如果这是你的意思。谢谢 还有一个请求/查询超时的示例? 看起来每次您需要 ../config/bookshelf 时都会创建新的 knex 实例 您可以(并且应该)验证 RDS 最大连接限制是否生效。只需使用标准 RDS 监控并关注 DB Connections 指标。另外,您是否在 AWS Lambda 上运行您的应用程序?这很容易让您同时运行数十个 lambda 调用,每个调用都打开与 RDS 的连接。 【参考方案1】:

我不认为是 RDS max_connections 导致了问题,假设您在任何时候都只有一个上述应用程序代码的实例在运行。

您的应用程序使用数据库连接池,最多可容纳 20 个连接。如果所有这些连接都在使用中,那么在连接超时之前,应用程序最多会等待acquireConnectionTimeout ms,即10000

所以我怀疑您的应用程序由于负载而需要处理大量数据库查询,或者有一些慢速查询占用连接。这会导致等待最终超时的连接的查询积压。调查可能的情况并更新我们。

您可以同时尝试的事情。

增加acquireConnectionTimeout。 增加连接池大小。

如果是由慢查询引起的,请在尝试上述方法之前对其进行优化。

记录慢速查询的可能方法:

在 RDS 上启用慢查询日志。 Knex query 事件记录事务持续时间(假设您正在使用事务)。

【讨论】:

【参考方案2】:

当客户端完成 MySQL 后,让它断开连接。

另外,检查wait_timeout 的值。降低它会强制断开连接,而不是“休眠”直到你回来。

【讨论】:

以上是关于如何在 RDS 上正确使用 Knex / Bookshelf 和 MySQL的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Knex.js 中正确设置“updatedAt”时间戳?

升级 Knex 后出现“获取连接超时”

Knex:Error Pool2 - 错误:分配资源时出错:连接 ECONNREFUSED

如何在 Knex 上使用 EXISTS 进行子查询?

在弹性豆茎上运行 knex 迁移

在对 Knex 进行单元测试时,如何模拟假数据库?