何时何地使用 knex.destroy?

Where and when to use knex.destroy?

我对在我的节点 API 中的什么地方使用 knex.destroy() 感到困惑。

如果我打开连接调用后不使用knex.destroy(),连接池会随着时间的推移被填满,导致错误:

Unhandled rejection TimeoutError: Knex: Timeout acquiring a connection. The pool is probably full. Are you missing a .transacting(trx) call?

如果我关闭连接,这对我来说很有意义,当我完成它时,

router.get('/users', function(req, res, next) {
    var select = knex.select('*').from('users');
    select.then((result) => {
        res.send(result);
    }).catch((error) => {
        res.send(error);
    }).finally(function() {
        knex.destroy(); // close it when I'm done
    });
});

已为单独的 API 个调用关闭连接:

Unhandled rejection Error: Unable to acquire a connection at Client_PG.acquireConnection (/var/app/current/node_modules/knex/lib/client.js:331:40)

那么我应该在何时何地实际破坏连接?同样,此 Node 应用程序仅用作 API。每个 API 调用都应该打开然后关闭连接,但 knex 似乎不喜欢这样。


需要knex的路由器文件:(我对每个路由器文件都这样做)

const knexService = require('../knexService');
const bookshelf = knexService.bookshelf;
const knex = knexService.knex;
let User = require('../models/User');

module.exports = function(app, router) {
   router.get('/users', function(req, res, next) {
       var select = knex.select('*').from('users');
       select.then((result) => {
           res.send(result);
       }).catch((error) => {
           res.send(error);
       }).finally(function() {
           knex.destroy(); // close it when I'm done
       });
   });
   ...

用户模型文件

const knexService = require('../knexService');
const bookshelf = knexService.bookshelf;
var BaseModel = require('./BaseModel');
var addressModel = require('./Address').Address;

var User = BaseModel.extend({
    tableName: 'users',
    hasTimestamps: true,
    addresses: function() {
        return this.hasMany(addressModel);
    }
});

KnexService.js

const knexfile = require('./knexfile');
const knex = require('knex')(knexfile.production);
const bookshelf = require('bookshelf')(knex);

module.exports.knex = knex;
module.exports.bookshelf = bookshelf;

KnexFile.js

module.exports = {

    development: {
        client: 'pg',
        version: '7.2',
        connection: {
            ...

knex.destroy() 应该在您想要 knex 丢弃池中的所有连接并停止所有计时器等时调用,以便应用程序可以正常结束。

所以基本上应该只在应用程序退出时调用,除非你正在做一些更复杂的事情,例如使用多个 knex 实例连接到多个数据库。

如果您 运行 没有连接并且池已满,则意味着您的代码有问题。可能的原因可能是:

  • 同时进行太多长时间持续的查询
  • 创建事务并且从不提交/回滚,因此这些连接永远不会返回到池中
  • knex/bookshelf/一些中间件中的错误

您应该尝试查明您的应用程序的哪些部分导致池填满,删除所有额外的代码,例如 bookshelf 相关内容,并找到可用于重现您的问题的最小设置(也删除所有交易开始。

您真的在使用 postgresql 7.2 还是正在连接一些自定义的 postgresql 兼容数据库?这可能会导致一些问题,但我认为这些问题不会以那种方式暴露出来,而是通过将断开的连接留在池中。