繁体   English   中英

在 nodejs 中重用 postgresql 连接池

[英]reusing postgresql connection pool in nodejs

我在 nodejs 中有以下 postgresql 连接文件:

// postgresql.js

"use strict";

const { Pool } = require('pg');

module.exports = new Promise((resolve, reject) => {
  const pool = new Pool({
    host: '127.0.0.1',
    port: 5432,
    user: 'postgres',
    password: 'postgres',
    database: 'postgres',
    connectionTimeoutMillis: 0,
    idleTimeoutMillis: 0,
    min: 10,
    max: 20,
  });

  resolve({ pool });
});

我使用的是 promise,因为稍后我将开始使用Google Cloud Secret Manager 秘密是异步获取的,因此在服务器启动时无法建立数据库连接。

在我的控制器文件中,我是这样使用它的:

// apicontroller.js

"use strict";

const postgresql = require('./postgresql');

app.get('/api/test', async (req, res, next) => {
// resolve the postgresql promise
const { pool } = await postgresql;

// resolve the pool.connect() promise
const client = await pool.connect();

// use the client object here
// eg. await client.query(...)
});

问题不在于它不起作用,相反,它就像一个魅力! 但我在问自己:我是在重用连接池,还是在每次请求这条路由时都创建一个新的连接(池)?

这是仅重用一次数据库连接的正确方法吗?

编辑:我只包含了相关的代码部分。

正如node-postgres的文档中所解释的那样,我将使用pool.query而不是使用(处理) client

单个查询,如果您不需要事务或只需要运行单个查询,池有一个方便的方法可以在池中的任何可用客户端上运行查询。 如果可以,这是使用 node-postgres 进行查询的首选方法,因为它消除了泄漏客户端的风险。

所以我的代码会像;

postgresql.js

let mainPool = null;

functiona createPool(){
  const pool = new Pool({
    host: '127.0.0.1',
    port: 5432,
    user: 'postgres',
    password: 'postgres',
    database: 'postgres',
    connectionTimeoutMillis: 0,
    idleTimeoutMillis: 0,
    min: 10,
    max: 20,
  });
  return pool;
}

function getPool(){
  if(!mainPool){
    mainPool = createPool();
  }
  return mailPool;
}

export default { getPool };

控制器.js

const { getPool } = require('./postgresql');

app.get('/api/test', async (req, res, next) => {
  getPool().query('SELECT * FROM users', [], (err, res) => {
    if (err) {
       return res.status(500).send(err);
    }
    return res.status(500).send(res);
  });
});

是的,您正在重用作为导出承诺的结果存储的相同池对象。 只有一个,没有代码可以创建第二个实例,无论您多久require一次,模块都只会被评估一次。

然而,错误处理有一个小问题——如果无法创建数据库池(例如,秘密无法加载),您需要在某处处理此问题(并且可能使应用程序崩溃),而不是等待unhandledrejection事件。

虽然您的代码很好,但请考虑在获取池(及其连接详细信息)之前不启动 http 服务器的替代方法,然后将池(不是对它的承诺)传递给所有路由。 这也确保了 http 服务器在其依赖项未能初始化时根本不会启动。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM