Node.js 应用程序中的 SequelizeConnectionError

Posted

技术标签:

【中文标题】Node.js 应用程序中的 SequelizeConnectionError【英文标题】:SequelizeConnectionError in Node.js application 【发布时间】:2019-08-03 16:24:25 【问题描述】:

我有一个奇怪的问题,不知道问题出在哪里。如有任何帮助,我将不胜感激。

我有 Node.js 应用程序,它在本地 Windows 10 计算机上运行良好。我在 CentOS 服务器中的 Docker 中成功运行了这个应用程序。此应用程序适用于远程 mysql 和 PostgreSQL 数据库。它工作了好几天,但今天我注意到我有错误。应用程序无法再连接到远程 MySQL 数据库。同时,如果我在本地计算机上运行应用程序或通过 DBeaver/dbForge 工具连接,我可以毫无问题地连接到远程 MySQL 数据库。

MySQL.js

const Sequelize = require('sequelize');

const sequelize = new Sequelize('database_name', 'username', 'password', 
    host: 'host',
    dialect: 'mysql'
);

sequelize.authenticate().then(() => 
    console.log('Connection to database has been established successfully.');
).catch(err => 
    console.error('Unable to connect to database:', err);
);

module.exports = sequelize;

routes.js

const express = require('express');

const router = express.Router();

const sequelize = require('../configurations/MySQL');
const Sequelize = require('sequelize');

const passport = require('passport');
require('../configurations/password')(passport);

router.post('/search_by_name', passport.authenticate('jwt', session: false, null), function(req, res) 
    const token = getToken(req.headers);
    if (token) 
        sequelize.query("LONG SQL QUERY", 
            replacements: 
                name: req.body.name,
            ,
            type: Sequelize.QueryTypes.SELECT
        ).then((locations) => 
            res.status(200).send(locations)
        ).catch((error) => 
            res.status(400).send(error);
        );
     else 
        return res.status(401).send(
            status: false,
            description: "Unauthorized"
        );
    
);

如您所见,我使用 sequelize 库将应用程序连接到远程 MySQL 数据库。我用来连接到远程 PostgreSQL 数据库的同一个库。正如我之前所说,只有当我尝试连接到 Docker 中的远程 MySQL 数据库时才会发生错误。 Docker 中的 PostgreSQL 连接没有错误。 Docker/network 内部可能存在这个问题吗?

依赖关系

"sequelize": "^4.42.0"
"mysql2": "^1.6.4"

我还认为问题的原因可能是因为很多池/连接和 sequelize 库不会自动关闭它们。这就是为什么我多次重新启动 docker сontainer 希望确认理论。不幸的是,错误并没有消失。

你觉得怎么样,会发生什么?

错误

Unable to connect to the database:  SequelizeConnectionError: connect ETIMEDOUT
    at Utils.Promise.tap.then.catch.err (/node_modules/sequelize/lib/dialects/mysql/connection-manager.js:149:19)
    at tryCatcher (/node_modules/bluebird/js/release/util.js:16:23)
    at Promise._settlePromiseFromHandler (/node_modules/bluebird/js/release/promise.js:512:31)
    at Promise._settlePromise (/node_modules/bluebird/js/release/promise.js:569:18)
    at Promise._settlePromise0 (/node_modules/bluebird/js/release/promise.js:614:10)
    at Promise._settlePromises (/node_modules/bluebird/js/release/promise.js:690:18)
    at _drainQueueStep (/node_modules/bluebird/js/release/async.js:138:12)
    at _drainQueue (/node_modules/bluebird/js/release/async.js:131:9)
    at Async._drainQueues (/node_modules/bluebird/js/release/async.js:147:5)
    at Immediate.Async.drainQueues [as _onImmediate] (/node_modules/bluebird/js/release/async.js:17:14)
    at processImmediate (timers.js:632:19)
  name: 'SequelizeConnectionError',
  parent:
    Error: connect ETIMEDOUT
       at Connection._handleTimeoutError (/node_modules/mysql2/lib/connection.js:173:17)
       at listOnTimeout (timers.js:324:15)
       at processTimers (timers.js:268:5)
     errorno: 'ETIMEDOUT',
     code: 'ETIMEDOUT',
     syscall: 'connect',
     fatal: true ,
  original:
    Error: connect ETIMEDOUT
       at Connection._handleTimeoutError (/node_modules/mysql2/lib/connection.js:173:17)
       at listOnTimeout (timers.js:324:15)
       at processTimers (timers.js:268:5)
     errorno: 'ETIMEDOUT',
     code: 'ETIMEDOUT',
     syscall: 'connect',
     fatal: true 

【问题讨论】:

【参考方案1】:

尝试在新 Sequelize 时添加池选项。参考document

Sequelize 将在初始化时设置一个连接池,因此您应该 理想情况下,如果您是,则只为每个数据库创建一个实例 从单个进程连接到数据库。如果您要连接到 来自多个进程的数据库,您必须为每个进程创建一个实例 进程,但每个实例都应该有一个最大连接池大小 “最大连接池大小除以实例数”。因此,如果 您希望最大连接池大小为 90,并且您有 3 个工作人员 进程,每个进程的实例应该有一个最大连接池 大小为 30。

const Sequelize = require('sequelize');

const sequelize = new Sequelize('database_name', 'username', 'password', 
    host: 'host',
    dialect: 'mysql',
    pool: 
      max: 15,
      min: 5,
      idle: 20000,
      evict: 15000,
      acquire: 30000
    ,
);

module.exports = sequelize;

另外,您可以在here查看更多选项

options.pool sequelize 连接池配置

options.pool.max 默认:5 池中最大连接数

options.pool.min 默认值:0 池中的最小连接数

options.pool.idle 默认:10000 最大时间,以毫秒为单位, 连接可以在被释放之前处于空闲状态。与 为正常工作而驱逐的组合,有关更多详细信息,请阅读 https://github.com/coopernurse/node-pool/issues/178#issuecomment-327110870

options.pool.acquire 默认:10000 最大时间,以毫秒为单位, 该池将在抛出错误之前尝试获取连接

options.pool.evict 默认值:10000 时间间隔,以毫秒为单位, 用于驱逐陈旧的连接。将其设置为 0 以禁用此功能。

options.pool.handleDisconnects 默认值:true 控制池是否应该 自动处理连接断开而不抛出错误

options.pool.validate 验证连接的函数。叫 与客户。默认函数检查客户端是一个对象,并且 它的状态没有断开

【讨论】:

一小时前我发现了一个新错误:User 'mysql_user' has exceeded the 'max_user_connections' resource (current value: 20)。我可以使用下一个命令set global max_connections = 200; 并修复我认为的错误,但问题的原因与窃取相关。它可能会在未来再次出现。在我看来,我需要进行重构。我需要使用我认为的池,并在每次 sql 查询后以某种方式关闭它。你有什么建议? 那么你对我最后的评论有什么想法吗?【参考方案2】:

简单来说,我想说这些类型的错误是在您输入了一些配置错误时出现的。这些是:

    数据库名称 用户名 密码

所以请在您的 congif.json 文件中交叉验证这些内容

【讨论】:

以上是关于Node.js 应用程序中的 SequelizeConnectionError的主要内容,如果未能解决你的问题,请参考以下文章

jQuery 函数不适用于 node.js 中的 express.js 路由

Node.js 不能要求同一目录中的 .js 文件

如何在heroku中显示node.js中的所有console.log?

node.js 中的 require('dotenv').config()

Node.js 中的面向行的流

Node.js:async.series 中的 forEach