首页 > 解决方案 > 在哪里破坏 knex 连接

问题描述

我将knexpg一起使用。

我有一个类似于以下的项目。

dbClient.js

const dbClient = require('knex')({
  client: 'pg',
  connection: {
    host: '127.0.0.1',
    user: 'user',
    password: 'password',
    database: 'staging',
    port: '5431'
  }
})

module.exports = dbClient

libs.js

const knex = require('./dbClient.js')

async function doThis(email) {
  const last = await knex('users').where({email}).first('last_name').then(res => res.last_name)
  // knex.destroy()
  return last
}

async function doThat(email) {
  const first = await knex('users').where({email}).first('first_name').then(res => res.first_name)
  // knex.destroy()
  return first
}

module.exports = {
  doThat,
  doThis
}

test01.js

const {doThis, doThat} = require('./libs.js');

(async () => {
  try {
    const res1 = await doThis('user53@gmail.com')
    console.log(res1)
    const res2 = await doThat('user53@gmail.com')
    console.log(res2)
  } catch (err) {
    console.log(err)
  }
})()

什么时候knex.destroy()被删除,libs.js如上图所示。node test01可以输出res1res2。但问题是连接无限期挂起,CMD 永远不会返回。

但是,如果我取消注释knex.destroy()libs.js则将doThis执行,CMD 将挂起,doThat因为不再有已关闭的连接doThis

我的问题是:

什么是最好的位置knex.destroy()?或者还有其他方法可以做到吗?

谢谢你的时间!

标签: node.jsknex.js

解决方案


Knex destroy()似乎是一次性操作。销毁连接后,下一次操作可能需要一个全新的连接池。

您导出的 db 客户端模块缓存到节点模块缓存中,并且不会在您每次需要时创建新的连接池。

这是预期用途,当应用程序退出或所有测试完成时,池应该被销毁。如果您有理由为每个操作创建/销毁连接(例如在无服务器环境中),则不应重用已销毁的客户端,而应每次都创建一个新实例。

否则,它就达不到连接池的目的。


关于 lambda/server-less 环境的更新:

从技术上讲,函数及其资源将在 lambda 函数运行后释放,这包括它可能打开的任何连接。这对于真正的无状态函数是必要的。因此建议在功能完成时关闭连接。但是,许多打开/关闭大量连接的函数最终可能会导致数据库服务器用尽连接(例如,请参阅此讨论)。一种解决方案可能是使用像 PgBouncer 或 PgPool 这样的中间池协商数据库服务器和 Lambda 函数之间的连接。

另一种方式是让平台提供商 (AWS) 为 lambda 环境添加特殊的池化功能,并让它们共享长期存在的资源。


推荐阅读