Опрос DB2 каждые 15 секунд, вызывающий утечку памяти в NodeJS - PullRequest
2 голосов
/ 17 июня 2019

У меня есть приложение, которое каждые 15 секунд проверяет наличие новых записей в DB2 на iSeries, используя IBM idb-connector .У меня есть асинхронные функции, которые возвращают результат запроса в socket.io, который генерирует событие с данными, включенными в интерфейс.Я сузил утечку памяти до асинхронных функций.Я прочитал несколько статей об общих причинах утечки памяти и о том, как их диагностировать.

MDN: управление памятью

Rising Stack: объяснение сбора мусора

Marmelab: узел поиска и исправления.Утечки памяти: практическое руководство

Но я до сих пор не вижу, в чем проблема.Кроме того, я не могу получить разрешение на установку node-gyp в системе, что означает, что большинство инструментов управления памятью недоступны для установки, например memwatch, heapdump и т. Д. Для установки требуется node-gyp.Вот пример того, какова основная структура функций.

    const { dbconn, dbstmt } = require('idb-connector');// require idb-connector

    async function queryDB() {
        const sSql = `SELECT * FROM LIBNAME.TABLE LIMIT 500`;

        // create new promise
        let promise = new Promise ( function(resolve, reject) {
            // create new connection 
            const connection = new dbconn();
            connection.conn("*LOCAL");
            const statement = new dbstmt(connection);
            statement.exec(sSql, (rows, err) => {
              if (err) {
                throw err;
              }
              let ticks = rows;
              statement.close();
              connection.disconn();
              connection.close();

              resolve(ticks.length);// resolve promise with varying data
            })
        });

        let result = await promise;// await promise
        return result;
    };

    async function getNewData() {
        const data = await queryDB();// get new data
        io.emit('newData', data)// push to front end
        setTimeout(getNewData, 2000);// check again in 2 seconds
    };

Есть идеи о том, где утечка?Я использую async / await неправильно?Или же я неправильно создаю / уничтожаю соединения с БД?Любая помощь в выяснении, почему этот код является утечкой, будет высоко оценена !!

Редактировать: Забыл упомянуть, что у меня ограниченный контроль над бэкэнд-процессами, так как они обрабатываются другой командой.Я только извлекаю данные, которыми они заполняют БД, и добавляю их на веб-страницу.

Редактировать 2: Я думаю, что я сузил его до того, что соединения с БД не очищаются должным образом.Но, насколько я могу судить, я следовал инструкциям, предложенным на их github repo .

Ответы [ 3 ]

2 голосов
/ 17 июня 2019

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

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

Я вижу несколько потенциальных преимуществ этого метода:

  1. Вы не отправляете десятки запросов, которые могут возвращать или не возвращать данные.
  2. Событие будет инициировано сразу после добавления записи в таблицу, а не через 15 секунд.
  3. Вам не нужно кодировать возможность одной или нескольких новых записей, это всегда будет 1, тот, который указан в очереди данных.
0 голосов
/ 28 июня 2019

да, вы должны закрыть соединение.Не делайте постоянных данных.по умолчанию вам не требуется обещание Statement.exe является асинхронным и обрабатывает его с помощью возвращаемого результата;keep setTimeout (getNewData, 2000); // снова проверяем через 2 секунды строку вне getNewData, иначе он становится рекурсивным бесконечным циклом.Пример кода

const {dbconn, dbstmt} = require('idb-connector');

const sql = 'SELECT * FROM QIWS.QCUSTCDT';
const connection = new dbconn(); // Create a connection object.

connection.conn('*LOCAL'); // Connect to a database.

const statement = new dbstmt(dbconn); // Create a statement object of the connection.

statement.exec(sql, (result, error) => {
  if (error) {
    throw error;
  }
  console.log(`Result Set: ${JSON.stringify(result)}`);

  statement.close(); // Clean up the statement object.
  connection.disconn(); // Disconnect from the database.
  connection.close(); // Clean up the connection object.

возвращаемый результат;});

 *async function getNewData() {
        const data = await queryDB();// get new data
        io.emit('newData', data)// push to front end
        setTimeout(getNewData, 2000);// check again in 2 seconds
    };*
change to 
   **async function getNewData() {
        const data = await queryDB();// get new data
        io.emit('newData', data)// push to front end

    };
setTimeout(getNewData, 2000);// check again in 2 seconds**
0 голосов
/ 26 июня 2019

Первое, на что следует обратить внимание, - это возможность открыть соединение с базой данных в случае ошибки.

if (err) {
   throw err;
}

Также в случае успеха connection.disconn(); и connection.close(); возвращают логические значения, указывающие на успешность операции ( согласно документации ) Всегда возможный сценарий - накапливать объекты подключения в сторонней библиотеке.Я бы проверил их.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...