【问题标题】:nodejs pg-pool doesn't seem to be poolingnodejs pg-pool 似乎没有池化
【发布时间】:2022-01-24 00:35:06
【问题描述】:

我一直试图让 nodejs 在我的应用程序中汇集 postgresql 连接,但未成功。这是我做的一个独立测试:

const config = require('../config/project_config.json');
const Pool = require('pg-pool');

var pool = new Pool({
    user: config.DB_USER,
    host: config.DB_HOST,
    database: config.DB_DB,
    password: config.DB_PW,
    port: 5432,
    max: 500,
    min: 200,
    idleTimeoutMillis: 0,
    connectionTimeoutMillis: 10000
});

for (var i=0; i<100; i++){
    pool.query(
        "SELECT id, email FROM players WHERE email ~ 'ltUser'",
        [],
        (err, res) => {
            if (err !== null && err != undefined){
                console.log(`err: ${err}`);
            }
            else{
                console.log(`num rows: ${res.rows.length}`);
            }
        });
}

我得到的结果是:

num rows: 400
num rows: 400
num rows: 400
num rows: 400
num rows: 400
num rows: 400
num rows: 400
num rows: 400
num rows: 400
num rows: 400
num rows: 400
num rows: 400
num rows: 400
num rows: 400
num rows: 400
num rows: 400
num rows: 400
num rows: 400
num rows: 400
num rows: 400
num rows: 400
num rows: 400
num rows: 400
num rows: 400
num rows: 400
num rows: 400
num rows: 400
num rows: 400
num rows: 400
num rows: 400
num rows: 400
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
err: Error: Connection terminated due to connection timeout
num rows: 400
num rows: 400
num rows: 400
num rows: 400
num rows: 400
num rows: 400
num rows: 400
num rows: 400
num rows: 400
num rows: 400
num rows: 400
num rows: 400
num rows: 400
num rows: 400
num rows: 400

如您所见,它引发了连接超时,这意味着在我创建池时它没有创建连接。在创建池时,我尝试了各种参数组合,包括keepalive: true,但似乎没有一个使 pg-pool 真正成为池连接。我也尝试过 pg 而不是 pg-pool。但得到了完全相同的结果,尽管我后来发现它基本上是相同的代码。

如果我使用运行时间较长的查询运行它,我可以连接到 psql 中的数据库并运行

SELECT datname,usename, ssl, client_addr, count(*
FROM pg_stat_ssl
  JOIN pg_stat_activity
    ON pg_stat_ssl.pid = pg_stat_activity.pid
where usename != 'azure_superuser'
group by datname,usename, ssl, client_addr;

并观察我的 IP 地址的连接数上升,然后再次下降。

是我做错了什么还是 pg-pool 坏了?

我在 ubuntu xenial 服务器上使用 nodejs v10.22.1。

【问题讨论】:

  • max: 500 似乎太高了。您的代码实际上是在尝试建立 100 个连接,而不是汇集任何东西。我猜您看到的连接超时来自您的数据库,而不是配置为接收那么多客户端。
  • 我创建池时它没有创建连接” - 这不是池的工作方式。仅在客户端需要时才创建连接,而不是在创建池时创建。
  • 该数据库最多可以处理 955 个客户端连接,目前仅将其中大约 200 个用于其他用途。如果我将数字设置为 20,它也不起作用。结果完全一样。
  • 顺便说一句 there is no min option(更多)
  • @Bergi 池化的目的是不要动态创建连接,因为这会占用大量资源。在我的 erlang 应用程序中,应用程序在启动时创建连接,并在需要时将它们从池中检出。如果它在运行查询时创建连接,则不是池。

标签: node.js postgresql node-postgres node-pg-pool


【解决方案1】:

事实证明 pg-pool 正在工作,只是没有按照我在 Java 和 Erlang 等其他编程语言方面的经验所期望的方式工作。 Nodejs 不会提前创建连接,而是在从池中检出连接时。

基于此,Nodejs 中池化的主要优点是程序员不必处理打开和关闭连接,并且连接可以重复使用。

【讨论】:

    【解决方案2】:

    如果你想打开一定数量的后端连接,比如说 200(这个数字太大了,你可能想要大约 64 个)

    然后您可以通过创建池来做到这一点,然后立即发出 200 个查询,不释放客户端

    然后释放所有 200 个客户端。

    从那时起,如果idleTimeoutMillis === 0,该池将永远拥有 200 个与数据库的打开连接,您可以将其用作初始化池

    var pool = new Pool({
        user: config.DB_USER,
        host: config.DB_HOST,
        database: config.DB_DB,
        password: config.DB_PW,
        port: 5432,
        max: 200,   // set max to 200 connections to the db
        //min: 200, // min is not a configuration option
        idleTimeoutMillis: 0,
        connectionTimeoutMillis: 10000
    });
    
    // create a list to hold all the "done" functions 
    //   that release clients
    let releaseClientDoneList = [];
    
    // open 200 clients, without releasing them
    for (var i=0; i<200; i++){
      // callback - checkout a client
      pool.connect((err, client, done) => {
          // asyncronously store the "done" function once the client 
          //   has connected to the db
          connectedNewClient(done);
        }
      )
    }
    
    let connectedNewClient = function (doneFunction) {
      // store the "done" function in the list
      releaseClientDoneList.push(doneFunction)
    
      // if the list has 200 "done" functions inside, 
      //   then we know we have initialised all the clients we want
      if (releaseClientDoneList.length >= 200) {
        
        // call all the "done" functions to release all the clients
        for (let doneFunctionReleasesClient of releaseClientDoneList) {
          doneFunctionReleasesClient();
        }
    
        // now we know there are 200 available, 
        //   initialised db connections in the pool
        databasePoolInitialised();
      }
    }
    
    let databasePoolInitialised = function () {
      // ... rest of your application code goes here
    }
    
    

    【讨论】:

      猜你喜欢
      • 2015-10-09
      • 2018-02-23
      • 1970-01-01
      • 2022-01-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-25
      • 2017-11-30
      相关资源
      最近更新 更多