Nodejs + SocketIO + MySql Соединения не закрываются должным образом и создают нагрузку на базу данных - PullRequest
0 голосов
/ 30 апреля 2020

У меня эта проблема уже больше пары месяцев, и я до сих пор не могу понять, как ее исправить. Кажется, что я испытываю большое количество соединений с нашей базой данных, и я предполагаю, что это потому, что наши соединения не закрываются должным образом, что заставляет их зависать в течение длительных периодов времени. В свою очередь это приводит к большим накладным расходам, которые иногда приводят к тому, что наше веб-приложение обрабатывает sh. В настоящее время приложение запускает пакет promise-mysql npm для создания соединения и запроса к базе данных. Наше веб-приложение использует socketio для запроса этих соединений с нашей базой данных * 1003. *

Я работаю с существующим кодом, который был здесь до меня, поэтому я не настроил его таким образом. Это немного сбивает с толку отладку этой проблемы, потому что я не очень знаком с тем, как закрываются соединения после успешного / неудачного запроса.

При регистрации ошибок с нашего сервера я получаю сообщения как это:

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' }

(Не уверен, имеет ли это какое-либо отношение к большому количеству соединений, которые я вижу или нет)

Я недавно изменил wait_timeout и interactive_timeout до 5000 в MySql, что намного ниже, чем значение по умолчанию 28800, но установка его на это предотвратила частое падение приложения.

Это код для создания соединения с базой данных:

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;

И это пример того, как выглядят сокеты:

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);
        })
    });

И это пример методов, которые вызываются из сокетов для установления соединения с база данных

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);
        }
    });
};

Я просто очень хочу понять, почему я замечаю такие большие затраты на соединения с базой данных, и что я могу сделать, чтобы решить эту проблему. Я действительно не хочу продолжать перезапускать мой сервер каждый раз, когда он выходит из строя, так что, надеюсь, я смогу найти некоторые ответы на это. Если у кого-то есть какие-либо предложения или они знают, что я могу изменить в своем коде, чтобы решить эту проблему, это мне очень поможет, спасибо!

РЕДАКТИРОВАТЬ

Это ошибки, которые я получаю от 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)

РЕДАКТИРОВАТЬ Есть ли способ понять, почему некоторые из этих соединений зависают или бездействуют?

1 Ответ

0 голосов
/ 30 апреля 2020

Вы открываете новое соединение для каждого запроса ... Открытие соединения происходит медленно, это требует много времени, и на вашем сервере определенно не разрешено неограниченное количество соединений. Пакет NodeJS mysql предоставляет механизм объединения, который был бы гораздо более эффективным для вас.

Цель состоит в том, чтобы как можно больше использовать соединения, а не всегда удалять их сразу после первого запроса .

В вашей базе данных. 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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...