如何在使用Express后的每个请求后关闭mysql连接?

时间:2018-04-12 18:19:09

标签: mysql node.js express database-connection

我有一个像这样的路由器文件:

import express from 'express';
import health from './health';
import surface from './surface';

const router = express.Router();

router.use('/health', health);
router.use('/surface', surface);

router.get('*', (req, res) => {
  res.status(404);
  res.json({
    message: 'Uknown API endpoint'
  });
});

export default router;

在每个路由中,我使用NPM mysql包创建连接,然后在我调用res.send()之前结束它。 IIRC创建连接并按查询结束它将是一个坏主意。

我尝试过做中间件:

router.use((req, res, next) => {
  next();
  mySingletonWrappingMysql.connection.end();
});

鉴于我的路由正在执行异步操作,endConnection调用过早发生。 next并不是真正的异步,所以我不能await next,我甚至不确定这是否是正确的方法/地方。此示例使用单例,因为我也不确定如何正确设置要在路径中使用的新实例。 req.param似乎是一个不是最佳原因的选项,似乎是特殊查询参数变种。

1 个答案:

答案 0 :(得分:5)

您需要连接到MySQL的连接池。这是一个可串行重用的连接资源池。你需要的时候拿一个,当你完成时就把它拿走。因此,每个请求,甚至每个中间件调用,都可以使用连接而不必担心并发(这对连接不起作用)。看到这个。 https://www.npmjs.com/package/mysql#pooling-connections

像这样设置你的游泳池,只需一次。每个node.js服务器实例都需要一个池,用于它使用的每个单独的MySQL服务器。

var mysql = require('mysql');
var pool  = mysql.createPool({
  connectionLimit : 10,
  host            : 'example.org',
  user            : 'bob',
  password        : 'secret',
  database        : 'my_db'
});

此createPool操作创建一个最多包含十个连接的池。每次使用池时,它都会检查其所有连接是否都很忙。如果没有,它会让你空闲使用。如果他们都忙,它会打开一个新的。但是,如果池中已经有connectionLimit个连接,它将等待一个空闲。

然后随意的一次性查询就像这样工作。在REST服务器中,您可能会发现对数据库的单个查询可以满足某些GET查询。这些都非常简单。没有必要明确地从池中获取或释放连接。并且,当您释放连接时,它将保持与DBMS的连接,以备将来的请求使用。如果满足特定请求需要两个或三个SELECT查询,您也可以使用此技术。但是,每个查询可能使用池中的不同连接。

 pool.query('SELECT whatever FROM whatever', 
   function (error, results, fields) {
     if (error) throw error;
     /* handle your results array */
 })

如果您需要为多个查询获取连接,那么它几乎一样简单,但您需要在完成后记住release()连接。当您的某些查询依赖于序列中先前查询的结果时,您需要执行此操作。

pool.getConnection(function(err, connection) {
    if (error) throw error;
    connection.query('INSERT INTO sometable ...', 
       function (error, results, fields) {
           if (error) {
               connection.release();
               throw error;
           }
           connection.query('INSERT INTO detail ... (LAST_INSERT_ID()...)', 
               function (error, results, fields) {
                  connection.release();
                  if (error) throw error;
               });
       });
});

您可能希望使用promises来避免函数嵌套,特别是如果您想运行一系列查询。