0

我正在使用 postgres-node (pg) 包运行节点服务器。

我编写了一个程序,它一次向我的 postgres 数据库请求 n 个查询(例如 20,000 个)。

当我对几个想要同时查询 20,000 个的客户执行此操作时,没有并行性。这意味着,第二个客户端的请求将排队,直到第一个客户端完成他的所有查询。

这是postgres的正常行为吗?如果是,如果没有并行性,我如何防止一个用户获得所有资源(其他人必须等待)?

这是我的代码:

const express = require('express');
const app = express();
const { Pool } = require("pg");
const pool = new Pool();


benchmark(){
    pool.connect((err, client, done) => {
      if (err) throw err;
      client.query("SELECT * from member where m_id = $1", [1], (err, res) => {
        done();
        if (err) {
          console.log(err.stack);
        } else {
          console.log(res.rows[0]);
        }
      });
    }); 
}


app.get('/', function(req, res) {
  for(let i=0;i<20000;i++){
    benchmark();
  }
});
4

1 回答 1

0

首先你需要创建一个连接池,为了方便起见,这里有一个单独的模块(node-pg-sql.js)中节点的pg的例子

节点-pg-sql.js:

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

const pool = new Pool(fileNameConfigPGSQL);

module.exports = {
  query: (text, params, callback) => {
    const start = Date.now()
    return pool.query(text, params, (err, res) => {
      const duration = Date.now() - start
  //    console.log('executed query', { text, duration, rows: res.rowCount })
      callback(err, res)
    })
  },
  getClient: (callback) => {
    pool.connect((err, client, done) => {
      const query = client.query.bind(client)

      // monkey patch 
      client.query = () => {
        client.lastQuery = arguments
        client.query.apply(client, arguments)
      }

      // Timeout 5 sek
      const timeout = setTimeout(() => {
     //   console.error('A client has been checked out for more than 5 seconds!')
     //   console.error(`The last executed query on this client was: ${client.lastQuery}`)
      }, 5000)

      const release = (err) => {
        // 'done' Methode - returns client to the pool
        done(err)

        // clear Timeouts
        clearTimeout(timeout)

        // reset der Query-Method before Monkey Patch
        client.query = query
      }

      callback(err, client, done)
    })
  }
}

在您的 postgresql.conf 中(在 Linux 上通常在 /var/lib/pgsql/data/postgresql.conf 下)将 max-connection 设置为所需的值:

max_connection = 300

记住:

每个 PostgreSQL 连接都会消耗 RAM 来管理连接或使用它的客户端。您拥有的连接越多,您将使用的 RAM 就越多,而这些 RAM 可用于运行数据库。

在增加您的同时max-connections,您还需要增加shared_bufferskernel.shmmax以便客户端连接增加有效。

每当您想从您的路线/端点之一运行查询时,只需要单独的客户端池文件,例如:

const db = require('../../../node-pg-sql');

module.exports = (router) => {

router.get('/someRoute', (req, res) => {
    console.log(`*****************************************`);
    console.log(`Testing pg..`);
    let sqlSelect = `SELECT EXISTS (
          SELECT 1 
          FROM   pg_tables
          WHERE  schemaname = 'someschema'
        )`;
    db.query(sqlSelect, (errSelect, responseSelect) => {
      if (errSelect) {
        /* INFO: Error while querying table */
        console.log(`*****************************************`);
        console.log(`ERROR WHILE CHECKING CONNECTION: ${errSelect}`);
      } 
      else {
        // INFO: No error from database
        console.log(`*****************************************`);
        console.log(`CONNECTION TO PGSQL WAS SUCCESSFUL..`);
        res.json({ success: true, message: responseSelect, data:responseSelect.rows[0].exists });

      }
    })
  });

}

编辑:

“没有平行度..”

Node 是异步的,您可以使用 Promise 或生成更多客户端/池并调整最大连接数(如我的回答中所述,但请记住主机的性能),但多个客户端运行大约 20.000 个查询,他们不会立即或并行地解决结果。你试图达到的确切目标是什么?

“这是 postgres 的正常行为吗?”

这是由于节点的事件循环以及运行 Postgres 的主机的某些性能限制。

于 2019-08-19T11:42:28.637 回答