Node.js应用程序中的SequelizeConnectionError
我有一个奇怪的问题,不知道问题出在什么地方.我将不胜感激.
I have strange problem and don't know in what place is the problem. I will be grateful for any help.
我有 Node.js 应用程序,该应用程序在本地Windows 10计算机上运行良好.我在CentOS服务器中的 Docker 中成功运行了该应用程序.该应用程序可用于远程MySQL和PostgreSQL数据库.几天正常工作,但是今天我注意到我有错误.应用程序无法再连接到远程MySQL数据库.同时,如果我在本地计算机上运行应用程序或通过DBeaver/dbForge工具进行连接,则可以毫无问题地连接到该远程MySQL数据库.
I have Node.js application which works fine in local windows 10 computer. I run this application successfully in Docker which is in CentOS server. This application works with remote MySQL and PostgreSQL databases. It worked correctly several days but yestoday I notice that I have error. Application can't connect to remote MySQL database anymore. In the same time I can connect to that remote MySQL database without any problem if I run application in my local computer or connect by DBeaver/dbForge tool.
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/网络内部是否可能出现此问题?
As you can see I use sequelize library to connect application to remote MySQL database. The same library I use to connect to remote PostgreSQL database. As I said before error happens only when I try to connect to remote MySQL database in Docker. There is no error with PostgreSQL connection in Docker. Is it possible that problem inside Docker/network?
依赖项:
"sequelize": "^4.42.0"
"mysql2": "^1.6.4"
我还认为问题的原因可能是因为大量的池/连接,而续集库不会自动关闭它们.因此,我多次重启dockerсontainer以期确认理论.不幸的是,错误并没有消失.
I also thought that the reason of the problem can be because of much pools/connections and sequelize library don't close them automatically. For thats why I restarted docker сontainer several times hoping to confirm the theory. Unfortunately the error do not disappear.
您如何看待?
错误:
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 }}
尝试在新的Sequelize时添加池选项.参考文档
Try to add pool option when new Sequelize. Reference document
Sequelize将在初始化时设置一个连接池,因此您应该理想情况下,如果您是每个数据库,则只能创建一个实例从单个进程连接到数据库.如果您要连接到来自多个进程的数据库,您必须为每个数据库创建一个实例进程,但每个实例应具有最大的连接池大小最大连接池大小除以实例数".因此,如果您希望最大连接池大小为90,并且有3个工作线程进程,每个进程的实例应该有一个最大连接池大小为30.
Sequelize will setup a connection pool on initialization so you should ideally only ever create one instance per database if you're connecting to the DB from a single process. If you're connecting to the DB from multiple processes, you'll have to create one instance per process, but each instance should have a maximum connection pool size of "max connection pool size divided by number of instances". So, if you wanted a max connection pool size of 90 and you had 3 worker processes, each process's instance should have a max connection pool size of 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;
此外,您可以在这里
options.pool 顺序化连接池配置
options.pool.max 默认值:5池中的最大连接数
options.pool.max default: 5 Maximum number of connection in pool
options.pool.min 默认值:0池中的最小连接数
options.pool.min default: 0 Minimum number of connection in pool
options.pool.idle 默认值:10000最长时间,以毫秒为单位,连接可以在释放之前处于空闲状态.与...一起使用逐出的正确组合,有关更多详细信息,请阅读 https://github.com/coopernurse/node-pool/issues/178#issuecomment-327110870
options.pool.idle default: 10000 The maximum time, in milliseconds, that a connection can be idle before being released. Use with combination of evict for proper working, for more details read https://github.com/coopernurse/node-pool/issues/178#issuecomment-327110870
options.pool.acquire 默认值:10000最长时间,以毫秒为单位,该池将尝试在引发错误之前获取连接
options.pool.acquire default: 10000 The maximum time, in milliseconds, that pool will try to get connection before throwing error
options.pool.evict 默认值:10000时间间隔(以毫秒为单位),驱逐过时的联系.将其设置为0以禁用此功能.
options.pool.evict default: 10000 The time interval, in milliseconds, for evicting stale connections. Set it to 0 to disable this feature.
options.pool.handleDisconnects 默认值:true控制池是否应该自动处理连接断开而不会引发错误
options.pool.handleDisconnects default: true Controls if pool should handle connection disconnect automatically without throwing errors
options.pool.validate 验证连接的功能.称为与客户.默认函数检查客户端是否是对象,并且它的状态没有断开
options.pool.validate A function that validates a connection. Called with client. The default function checks that client is an object, and that its state is not disconnected