gpt4 book ai didi

javascript - Nodejs + SocketIO + MySql 连接未正确关闭并创建数据库开销

转载 作者:行者123 更新时间:2023-12-01 16:10:20 24 4
gpt4 key购买 nike

我已经遇到这个问题两个多月了,但似乎仍然无法弄清楚如何解决它。似乎我遇到了与数据库的大量连接,我认为这是因为我们的连接没有正确关闭导致它们长时间挂起。作为返回,这会导致大量开销,偶尔会导致我们的 Web 应用程序崩溃。目前应用程序运行 promise-mysql npm 包来创建连接和查询数据库。我们的 Web 应用程序使用 socketio 请求这些连接到我们的 mysql 数据库。

我正在使用我之前的现有代码,所以我没有以这种方式设置它。这让我在调试这个问题时更加困惑,因为我不太熟悉在成功/不成功查询后连接是如何关闭的。

当从我们的服务器记录错误时,我收到这样的消息:

db error { Error: Connection lost: The server closed the connection.
at Protocol.end (/home/ec2-user/myapp/node_modules/mysql/lib/protocol/Protocol.js:113:13)
at Socket.<anonymous> (/home/ec2-user/myapp/node_modules/mysql/lib/Connection.js:109:28)
at Socket.emit (events.js:185:15)
at Socket.emit (domain.js:422:20)
at endReadableNT (_stream_readable.js:1106:12)
at process._tickCallback (internal/process/next_tick.js:178:19) fatal: true, code: 'PROTOCOL_CONNECTION_LOST' }

(不确定这是否与我看到的大量连接有关)

我最近将 MySql 中的 wait_timeoutinteractive_timeout 更改为 5000,这比默认值低很多28800,但将其设置为此可阻止应用程序如此频繁地崩溃。

这是创建数据库连接的代码:

数据库.js文件

import mysql from 'promise-mysql';
import env from '../../../env.config.json';

const db = async (sql, descriptor, serializedParameters = []) => {
return new Promise( async (resolve, reject) => {
try {
const connection = await mysql.createConnection({
//const connection = mysql.createPool({
host: env.DB.HOST,
user: env.DB.USER,
password: env.DB.PASSWORD,
database: env.DB.NAME,
port: env.DB.PORT
})
if (connection && env.ENV === "development") {
//console.log(/*"There is a connection to the db for: ", descriptor*/);
}
let result;

if(serializedParameters.length > 0) {
result = await connection.query(sql, serializedParameters)
} else result = await connection.query(sql);
connection.end();
resolve(result);
} catch (e) {
console.log("ERROR pool.db: " + e);
reject(e);
};
});
}

export default db;

这是套接字的示例:

sockets.js 文件

socket.on('updateTimeEntry', async (time, notes, TimeEntryID, callback) => {
try {
const results = await updateTimeEntry(time, notes, TimeEntryID);
callback(true);
//socket.emit("refreshJobPage", false, "");
}
catch (error) {
callback(false);
}
});

socket.on('selectDatesFromTimeEntry', (afterDate, beforeDate, callback) => {
const results = selectDatesFromTimeEntry(afterDate, beforeDate).then((results) => {
//console.log('selectLastTimeEntry: ', results);
callback(results);
})
});

这是从套接字调用以连接到数据库的方法的示例

timeEntry.js文件

import db from './database';

export const updateTimeEntry = (time, notes, TimeEntryID) => {
return new Promise(async (resolve, reject) => {
try {
const updateTimeEntry = `UPDATE mytable SET PunchOut = NOW(), WorkTimeTotal = '${time}', Notes = "${notes}" WHERE TimeEntryID = '${TimeEntryID}';`

const response = await db(updateTimeEntry, "updateTimeEntry");
resolve(response[0]);
} catch (e) {
console.log("ERROR TimeEntry.updateTimeEntry: " + e);
reject(e);
}
});
};

//Gets a List for Assigned Jobs
export const selectDatesFromTimeEntry = (afterDate, beforeDate) => {
return new Promise(async (resolve, reject) => {
try {
const selectDatesFromTimeEntry = `SELECT * FROM mytable.TimeEntry WHERE PunchIn >= '${afterDate}' && PunchIn < '${beforeDate}';`
//console.log("Call: " + selectDatesFromTimeEntry);
const response = await db(selectDatesFromTimeEntry, "selectDatesFromTimeEntry");
//console.log("Response: " + response);
resolve(response);
} catch (e) {
console.log("ERROR TimeEntry.selectDatesFromTimeEntry: " + e);
reject(e);
}
});
};

我真的很想弄清楚为什么我注意到我的数据库连接开销如此之大,以及我可以做些什么来解决它。我真的不想在每次崩溃时都重新启动我的服务器,所以希望我能找到一些答案。如果有人有任何建议或知道我可以在我的代码中更改什么来解决这个问题,那将对我有很大帮助,谢谢!

编辑 1

这些是我从 mysql

得到的错误
2020-04-30T11:12:40.214381Z 766844 [Note] Aborted connection 766844 to db: 'mydb' user: 'xxx' host: 'XXXXXX' (Got timeout reading communication packets)
2020-04-30T11:12:48.155598Z 766845 [Note] Aborted connection 766845 to db: 'mydb' user: 'xxx' host: 'XXXXXX' (Got timeout reading communication packets)
2020-04-30T11:15:53.167160Z 766848 [Note] Aborted connection 766848 to db: 'mydb' user: 'xxx' host: 'XXXXXX' (Got timeout reading communication packets)

编辑 2

有什么方法可以让我了解为什么其中一些连接会挂起或空闲?

编辑 3

我一直在考虑使用 pool 来代替,因为它似乎是一种更具扩展性且更适合我的应用程序的解决方案。如何使用现有代码实现此目的?

最佳答案

您正在为每个查询打开一个新连接...打开一个连接很慢,这样做会产生很多开销,而且您的服务器当然不允许无限数量的连接。 NodeJS mysql 包提供了一种池化机制,这对您来说效率更高。

目标是尽可能多地重用连接,而不是总是在第一次查询后立即处理它们。

在您的 db.js 中,在启动时创建一个池并使用它:

var pool  = mysql.createPool({
connectionLimit : 10, //Number of connections to create.
host: env.DB.HOST,
user: env.DB.USER,
password: env.DB.PASSWORD,
database: env.DB.NAME,
port: env.DB.PORT
});

要执行您的查询,您只需这样做:

await pool;
return pool.query(sql, serializedParameters);

关于javascript - Nodejs + SocketIO + MySql 连接未正确关闭并创建数据库开销,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61526871/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com