最近项目部署上线后发现了一个数据库连接的问题,网上对于这个问题的解答也很少,后续自己找方法解决了,所以在这里记录一下。
问题是这样的,我用的node的express框架开发后端,项目部署上线后没什么问题,但是过了一段时间没去访问项目,也就是没有操作数据库后数据库就会断开连接(据说是因为mysql的默认配置连接时间是8小时,超过这个时间没有连接的话就会断开连接),mysql会报错Error:read ECONNRESET
以及Error:Cannot enqueue Query after fatal error
,这个时候访问项目就会报错,为了解决这个问题我也尝试了很多方法,无论是修改express连接mysql的配置项、express中监听mysql连接断开重连还是直接简单粗暴延长mysql的连接时间都不行,后面想了个办法,监听mysql断开连接后执行脚本命令重启express后端项目,这样虽然算是解决这个问题的偏方了但是效果确实不错,接下来讲讲具体代码实现吧
首先在js代码中执行终端命令需要用到child_process插件的exec命令,所以先安装一下child_process
shell
npm install child_process
然后执行的终端命令是在项目启动的情况下重启项目,在这里我用pm2来实现重启的需求
首先引用官方的一句话来介绍一下pm2:PM2 是一个守护进程管理工具,帮助您管理和守护您的应用程序。它以简单直观的 CLI 命令行方式进行工作
。
简单来说就是可以管理node项目,以进程的方式启动项目并能保持项目不断开,同时还提供了很多api来操作启动的项目进程,我这里就需要用到pm2重启项目进程的apipm2 restart all
首先安装pm2
shell
npm install pm2 -g
我的项目使用了docker,所以要是想在docker中配合使用pm2 的话,还需要在dockerfile中配置安装pm2,以pm2启动项目代替直接node启动项目
shell
#node服务器
FROM node:16
LABEL name="blog-express4"
LABEL version="latest"
RUN mkdir -p /usr/src
COPY . /usr/src
WORKDIR /usr/src
RUN npm install
# 在当前docker实例中全局安装pm2
RUN npm install pm2 -g
EXPOSE 4000
# pm2启动项目代替直接node启动项目
# CMD ["node","app.js"]
CMD ["pm2-runtime","app.js"]
具体在docker中使用pm2的更多细节可以看pm2的官网:在docker中使用pm2
然后在项目连接mysql的配置文件中监听到mysql断开连接后执行pm2重启项目的api:
package.json配置node命令:
json
{
"name": "node-express4",
"version": "0.0.0",
"private": true,
"scripts": {
"start": "pm2 start app.js",
"restart": "pm2 restart all",
"stop": "pm2 stop all",
"logs": "pm2 logs",
"ls": "pm2 ls"
},
"dependencies": {
"busboy": "^1.6.0",
"cookie-parser": "~1.4.4",
"cors": "^2.8.5",
"debug": "~2.6.9",
"express": "~4.16.1",
"http-errors": "~1.6.3",
"jsonwebtoken": "^8.5.1",
"morgan": "~1.9.1",
"mysql": "^2.18.1",
"pm2": "^5.3.0",
"pug": "2.0.0-beta11"
}
}
db/index.js数据库连接配置文件:
js
//连接mysql数据库
var mysql = require('mysql')
var { exec } = require('child_process');
var mysqlConfig = {
//连接远程数据库
host: '114.55.75.3',
user: 'root',
// user: 'haixtx', //docker部署mysql
password: 'xxx',
database: 'blog',
port: 3306,
}
// 以pm2接管项目重新启动项目
var restartProject = function(){
// process.exit()
// 执行终端命令
exec('npm run restart', (error, stdout, stderr) => {
if (error) {
console.error(`重启项目失败: ${error}`);
return;
}
console.log(`重启项目成功: ${stdout}`);
});
}
let connection
function handleDisconnect () {
connection = mysql.createConnection(mysqlConfig)
connection.connect((err) => {
if (err) {
// console.error('mysql连接错误,2s后重连: ' + err.stack)
// // 2s后重连
// setTimeout(handleDisconnect, 2000)
return
}
console.log('数据库连接成功,mysql连接进程id: ' + connection.threadId)
})
// 监听MySQL连接的end事件,一旦连接断开则自动重连
connection.on('end', function() {
console.log('数据库连接已断开,pm2重启项目重连数据库...')
// 执行exec终端命令
restartProject()
})
}
handleDisconnect ()
module.exports = connection
至此就解决了这一问题
项目的数据库长时间不操作后会自动重启后端项目重新连接数据库