每 15 秒查询一次 DB2 导致 NodeJS 内存泄漏

问题描述 投票:0回答:4

我有一个应用程序,它使用 IBM 的 idb-connector 在 iSeries 上每 15 秒检查一次 DB2 中的新条目。我有异步函数,它将查询结果返回到 socket.io,后者发出一个事件,其中包含前端的数据。我已将内存泄漏范围缩小到异步函数。我读过多篇有关常见内存泄漏原因以及如何诊断它们的文章。

MDN:内存管理

Rising Stack:垃圾收集解释

Marmelab:查找并修复 Node.js 内存泄漏:实用指南

但我还是没看出问题出在哪里。另外,我无法获得在系统上安装 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 上建议的说明。

node.js memory-management async-await db2 ibm-midrange
4个回答
1
投票

我不知道你的具体问题的答案,但我可能会以不同的方式解决这个问题,而不是每 15 秒发出一次查询。原因是当环境可以告诉我发生了事件时,我通常不喜欢钓鱼探险。

因此,您可能想尝试一个数据库触发器,在添加时将行的键加载到数据队列中,甚至在必要时更改或删除。然后,您可以放入异步调用来等待数据队列上的记录。这是更实时的,并且仅当记录显示时才调用事件处理程序。处理程序可以从数据库中获取特定记录,因为您知道它是关键。数据队列比数据库 IO 快得多,并且对触发器的开销很小。

我看到了这种方法的一些潜在优势:

  1. 您不会发出数十个可能返回或不返回数据的查询。
  2. 该事件将在记录添加到表中时立即触发,而不是 15 秒后。
  3. 您不必为一条或多条新记录的可能性进行编码,它将始终为 1,即数据队列中提到的记录。

1
投票

是的,您必须关闭连接。 不要制作 const 数据。默认情况下,你不需要promise语句。exec是异步的,并通过返回结果处理它; 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
投票

首先要注意的是,如果出现错误,可能会打开数据库连接。

if (err) {
   throw err;
}

如果成功,

connection.disconn();
connection.close();
返回布尔值,表明操作成功(根据文档) 总是可能的情况是在第三方库中堆积连接对象。 我会检查那些。


0
投票

这被证实是我正在使用的 idb-connector 库中的内存泄漏。链接到 github 问题这里。基本上有一个变量从未在库的核心代码中释放其内存。添加了新版本,可以在这里查看提交。

© www.soinside.com 2019 - 2024. All rights reserved.