针对处理并发量大的数据的经历(Nodejs经验分享)

针对处理并发量大的数据的经历(Nodejs经验分享)

网关采用nodejs 的TCP模块接收GPS上报上来的数据,采用Http模块的将解析完的数据发送到java写的服务中去。该服务是用structs + sping +ibatis架构,数据库oracle。web服务器采用tomcat,服务器linux red hat 64位,16G内存。第一个问题出现了,当GPS终端量增大了,慢慢的将16G的内存耗尽。时间2-3天。经过排查是数据库的处理速度跟不上服务发送的数据。本来想部署weblogic后来由于出现问题,老是部署失败。最后升级了数据库版本。莫名其妙的好了。郁闷!。前不久数据库都被爆掉了。第二个问题,nodejs网关有时候会出现http连接队列已满。造成无法向服务发送数据。重启后即可。这些问题目前还无法彻底解决只能定时去重启网关。

如果大牛知道请告之。谢谢。。。。以后还会分享一些遇到的技术问题。


2 回复

针对处理并发量大的数据的经历(Nodejs经验分享)

在处理高并发量的数据时,我遇到了一些挑战,并且通过一系列的实践和优化,最终找到了有效的解决方案。以下是我在这个过程中的一些经验和心得。

环境描述

我们使用Node.js的TCP模块来接收来自GPS终端的数据,并通过HTTP模块将解析后的数据发送到一个基于Java的后端服务中。具体技术栈如下:

  • 前端:Node.js(TCP & HTTP模块)
  • 后端:Java(Struts + Spring + iBatis)
  • 数据库:Oracle
  • Web服务器:Tomcat
  • 操作系统:Linux Red Hat 64位,16G内存

第一个问题:内存耗尽

最初,当GPS终端的数量增加时,系统逐渐耗尽了16G的内存。经过排查,发现主要问题是数据库处理速度跟不上前端发送的数据。为了应对这个问题,我们采取了以下几个步骤:

  1. 升级数据库版本:我们将Oracle数据库从较旧的版本升级到了最新版本。新版本的Oracle在性能上有显著提升,能够更好地处理大量并发请求。

    // 示例代码:升级数据库连接配置
    const oracledb = require('oracledb');
    async function connectToDatabase() {
      try {
        await oracledb.createPool({
          user: 'username',
          password: 'password',
          connectString: 'localhost/XE'
        });
        console.log('Connected to database');
      } catch (err) {
        console.error(err);
      }
    }
    
  2. 优化SQL查询:通过优化SQL查询语句,减少数据库的负担。例如,使用索引、避免全表扫描等。

第二个问题:HTTP连接队列已满

另一个问题是Node.js网关有时会出现HTTP连接队列已满的情况,导致数据无法发送。为了解决这个问题,我们采取了以下措施:

  1. 调整HTTP客户端配置:通过调整HTTP客户端的配置,增加最大连接数和超时时间,可以有效缓解连接队列已满的问题。

    // 示例代码:配置HTTP客户端
    const http = require('http');
    
    const options = {
      hostname: 'backend-service.com',
      port: 80,
      path: '/api/data',
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      }
    };
    
    const req = http.request(options, (res) => {
      res.on('data', (chunk) => {
        console.log(`Response chunk: ${chunk}`);
      });
    });
    
    req.on('error', (e) => {
      console.error(`Problem with request: ${e.message}`);
    });
    
    req.write(JSON.stringify({ data: 'some-data' }));
    req.end();
    
  2. 异步处理:通过使用异步编程模型,如async/await,可以更有效地管理并发请求,减少阻塞和延迟。

    // 示例代码:使用async/await
    async function sendData(data) {
      return new Promise((resolve, reject) => {
        const req = http.request(options, (res) => {
          let data = '';
          res.on('data', (chunk) => {
            data += chunk;
          });
          res.on('end', () => {
            resolve(data);
          });
        });
    
        req.on('error', (e) => {
          reject(e);
        });
    
        req.write(JSON.stringify(data));
        req.end();
      });
    }
    
    // 使用async/await调用
    async function handleData(data) {
      try {
        const response = await sendData(data);
        console.log(response);
      } catch (error) {
        console.error(error);
      }
    }
    

总结

通过上述方法,我们成功地解决了内存耗尽和HTTP连接队列已满的问题。希望这些经验和技巧能对你有所帮助。如果你有更多问题或更好的建议,请留言交流!


以上就是我在处理高并发数据时的一些经历和解决方案。如果您有任何疑问或建议,请随时联系我。期待与您的进一步交流!


在处理高并发数据时,Node.js 提供了很好的异步非阻塞 I/O 模型,可以有效应对并发量大的场景。以下是一些针对您描述问题的解决方案和建议:

解决方案

  1. 优化数据库处理速度

    • 升级数据库版本确实能提高性能。
    • 使用批量操作减少数据库请求次数。例如,在 Node.js 中使用 oracledb 模块进行批量插入。
    const oracledb = require('oracledb');
    
    async function batchInsert(data) {
        let conn;
        try {
            conn = await oracledb.getConnection({ user: 'username', password: 'password', connectString: 'localhost/XE' });
            await conn.executeMany(`
                INSERT INTO gps_data (id, lat, lng)
                VALUES (:id, :lat, :lng)`, data);
        } catch (err) {
            console.error(err.message);
        } finally {
            if (conn) { 
                try {
                    await conn.close();
                } catch (err) {
                    console.error(err.message);
                }
            }
        }
    }
    
  2. 优化HTTP请求队列

    • 使用连接池管理HTTP客户端连接,避免每次请求都创建新连接。
    • 可以使用第三方库如 axiosnode-fetch 并配合连接池。
    const axios = require('axios');
    const pool = [];
    
    async function sendToServer(data) {
        if (pool.length === 0) {
            for (let i = 0; i < 5; i++) { // 创建5个连接
                pool.push(axios.create({ baseURL: 'http://your-service-url' }));
            }
        }
        const client = pool.shift();
        try {
            await client.post('/endpoint', data);
        } catch (err) {
            console.error(err);
        } finally {
            pool.push(client); // 回收连接
        }
    }
    
  3. 监控与报警机制

    • 建立监控系统,及时发现并处理内存泄露或连接队列满等问题。
    • 使用如 pm2 进行进程管理,设置自动重启策略。
    pm2 start app.js --watch --max-memory-restart 1G
    

通过上述方法,您可以更好地处理高并发情况下的数据传输问题,并提升系统的稳定性和性能。希望这些建议对您有所帮助。

回到顶部