如何在启动时使Node.js MySQL连接池可用

4
每次运行 showData.js 脚本时,它会调用:
var pool  = mysql.createPool({

有没有办法在node.js服务器启动时创建连接池?

我尝试在server.js中添加createPool,但当我调用时似乎无法从我的showData.js脚本访问该对象。

pool.getConnection(function(err,connection){

在node.js服务器启动时,开启连接池是否必要?

即使调用connection.release并且脚本关闭,mysql连接池是否仍然存在?

编辑 @Marco,我得到了ReferenceError: pool is not defined.的错误信息。我知道问题在于我没有将pool引入showData.js中。根据node.js的说法,多次加载一个模块是可以的。

来自https://nodejs.org/api/modules.html

缓存

模块在第一次加载后被缓存。这意味着(除其他事项外)如果返回的是同一个文件,则每次调用require('foo')都会得到完全相同的对象。

多次调用require('foo')可能不会导致模块代码被执行多次。这是一个重要的特性。有了它,“部分完成”的对象可以被返回,从而允许加载传递依赖关系,即使它们会导致循环。

如果要使模块执行多次,请导出一个函数并调用该函数。

这是我的最新设置:

lib/dbpool.js

var mysql = require('mysql');
var pool  = mysql.createPool({
  connectionLimit : 10,
  host            : 'someco.com',
  user            : 'pinco',
  password        : 'pallino'
});

module.exports = pool;

server.js

const pool = require('./lib/dbpool');

showData.js

'use strict';
module.exports = router => {
    router.route('/show').post((req, res) => {
        pool.query('SELECT * FROM db.users', function(err, rows, fields) {

我需要在server.js和showData.js两个文件中都添加以下这行代码吗?
const pool = require('./lib/dbpool');

如果在 server.js 中不需要使用 pool,你可以只在 showData.js 中导入该模块。 如果两个文件都需要使用它,你可以在两个文件中都添加 "require"。 - Marco Altieri
2个回答

15

定义一个名为lib/dbpool.js的模块,其内容如下:

var mysql = require('mysql');
var pool  = mysql.createPool({
  connectionLimit : 10,
  host            : 'someco.com',
  user            : 'pinco',
  password        : 'pallino'
});

module.exports = pool;

在您的应用程序代码中使用:

const pool = require('./lib/dbpool');

app.post('/your/app/url', (req, res) => {
  pool.query('your query', function(err, rows, fields) {
    if (err) throw err;
    /* Manage your results here */

  });
}

pool.query实际执行的是:pool.getConnection(),然后是connection.query(),最后是connection.release()


3
这是很好的信息。谢谢Marco。我的担忧是我的应用程序代码每分钟会被调用数千次。每次创建常量池会发生什么?我担心连接池可能应该在其他地方创建并保持打开状态。或者这是一个不必要的担忧吗?在我看来,createPool 不断被调用,而我认为连接池应该只打开一次并保持打开状态。 - mcmacerson
1
@mcmacerson 连接池应该只创建一次。如果你在 app.js 中导入你的模块,并且在那里有所有被调用的端点,连接池将只会被创建一次并且连接将被重复使用。 - Marco Altieri
1
如果每个模型都在自己的文件中,且每个模型都需要 pool,那么代码 const pool = require('./lib/dbpool'); 是否会在每次实例化模型时重新运行连接代码? - Kearney Taaffe
1
@KearneyTaaffe 我相信,根据Marco Altieri的评论,如果在app.js中导入连接代码,则只运行一次。如果有更好的理解,请纠正我。 - mcmacerson
我在我的Node.js应用程序中使用了这个模式。我每秒处理60个事务。对于每个请求,我都会执行一次数据库写入操作。但是,在持续几分钟的高TPS后,我的Docker容器崩溃了。有人遇到过这个问题吗? - Chamith Madusanka
这样做会不会在每次我在控制器中导入pool而不是在app.js中导入时创建一个新的连接池? - Niv Apo

1
这个解决方案使用一个变量来保存池,并在第一次初始化后返回它。

const mysql = require("mysql2/promise");
var pool;
module.exports = function getPool() {
    if (!pool) {
      const config = {
        connectionLimit: 100,
        host: process.env.SQL_HOST,
        user: process.env.SQL_USER,
        password: process.env.SQL_PASSWORD,
        database: process.env.SQL_DATABASE,
        debug:false,
        waitForConnections: true,
        multipleStatements: true
      };
      pool = mysql.createPool(config);
    }
    return pool;        
};

const getPool = require('./db.js');

async function handleREquest(req, res) {
   const result = getPool().query('...');
   //...
}

基于这个 Github 代码的编程:HERE

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接