簡體   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