【问题标题】:How do I close mysql connection after each request with Express?如何在每次使用 Express 请求后关闭 mysql 连接?
【发布时间】:2018-09-23 00:21:45
【问题描述】:

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

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 似乎不是最佳选择,因为它似乎适用于特殊查询参数变量。

【问题讨论】:

    标签: mysql node.js express database-connection


    【解决方案1】:

    您需要一个到 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 操作会创建一个最多包含 10 个连接的池。每次使用池时,它都会检查它的所有连接是否都忙。如果没有,它会给你一个空闲的使用。如果他们都忙,它会打开一个新的。但是,如果池中已经有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;
                   });
           });
    });
    

    您可能希望使用 Promise 来避免这种函数嵌套,尤其是在您想运行一系列查询时。

    【讨论】:

    • 在什么情况下我想做一次性查询?保证有一个查询的 api 端点?我想我总是想用第二种方法来确保我只使用一个连接。但无论哪种方式,这个模型都意味着我知道哪个查询是最后一个,所以最后一个调用者将释放连接。当我的脚本结束执行时,没有什么好的方法可以释放吗?
    • 其实只是跟人聊了半天。让我知道这是否有任何错误。如果没有,你会得到绿色检查:) 每个节点服务器应该有一个池。它应该为它在该池中附加到的每个数据库建立一个连接。例如,如果您有一个主设备和两个从设备,则需要三个连接。我永远不会手动结束或释放连接,因为它们应该保持打开状态以供重复使用。
    • 好的,对于重复的 cmets 感到抱歉。将其标记为好,尽管如果您的答案澄清了在使用池时没有真正的理由要手动关闭事物,您的答案会更好;)
    • 请查看我的编辑。每个 node.js 实例都需要一个连接池,用于它使用的每个单独的 MySQL 服务器。给定池中的所有连接都指向同一个 MySQL 服务器。 node.js/express 实例可以处理许多并发请求。使用连接池允许每个并发请求执行 MySQL 操作,而无需等待其他请求完成。
    • 如果我不释放连接,它会在我想象的某个超时后自动释放?基本上认为我不需要手动释放连接,出于同样的原因,我不需要在没有池的情况下手动结束连接。
    猜你喜欢
    • 2020-02-10
    • 1970-01-01
    • 2015-11-08
    • 2019-08-23
    • 2020-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多