针对处理并发量大的数据的经历(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连接队列已满。造成无法向服务发送数据。重启后即可。这些问题目前还无法彻底解决只能定时去重启网关。
如果大牛知道请告之。谢谢。。。。以后还会分享一些遇到的技术问题。
针对处理并发量大的数据的经历(Nodejs经验分享)
在处理高并发数据时,我们经常会面临各种挑战。本文将分享我们在使用 Node.js 处理 GPS 数据时遇到的一些问题及解决方案。
环境配置
我们的网关采用 Node.js 的 net
模块来接收 GPS 终端上报的数据。然后通过 http
模块将解析后的数据发送到一个 Java 服务。该服务使用了 Spring + Struts + iBatis 架构,并且数据库是 Oracle。Web 服务器为 Tomcat,操作系统为 Linux Red Hat 64 位,服务器配置为 16G 内存。
第一个问题:内存耗尽
起初,当 GPS 终端数量增加时,系统会逐渐耗尽 16G 的内存。这种情况通常会在 2 到 3 天内发生。经过仔细排查,我们发现问题是由于数据库处理速度跟不上服务发送的数据速率。
示例代码:
const net = require('net');
const http = require('http');
// 创建 TCP 服务器
const server = net.createServer((socket) => {
socket.on('data', (data) => {
// 解析数据
const parsedData = parseGPSData(data);
// 发送数据到 HTTP 服务
sendToService(parsedData);
});
});
server.listen(8080, () => {
console.log('TCP Server listening on port 8080');
});
function parseGPSData(data) {
// 实现数据解析逻辑
}
function sendToService(data) {
const options = {
hostname: 'localhost',
port: 3000,
path: '/api/data',
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
};
const req = http.request(options, (res) => {
res.on('data', (chunk) => {
console.log(`Received response: ${chunk}`);
});
});
req.on('error', (e) => {
console.error(`Problem with request: ${e.message}`);
});
req.write(JSON.stringify(data));
req.end();
}
解决办法:
- 优化数据库性能:最初我们考虑升级硬件或使用更强大的 Web 服务器(如 WebLogic),但这些尝试都失败了。最终,我们决定升级数据库版本,这显著提高了数据库处理速度。
- 调整数据处理逻辑:可以考虑引入消息队列(如 RabbitMQ 或 Kafka)来异步处理数据,从而减轻数据库压力。
第二个问题:HTTP 连接队列已满
另一个问题是,当 GPS 终端数量增加时,Node.js 网关有时会出现 HTTP 连接队列已满的情况。这会导致数据无法正常发送。重启网关后,问题暂时得到解决。
解决办法:
- 增加连接池大小:可以通过配置 HTTP 客户端来增加连接池的大小。
- 负载均衡:可以考虑使用负载均衡器(如 Nginx)来分发请求,避免单点过载。
- 异步处理:确保数据处理逻辑是非阻塞的,以提高系统的响应能力。
希望这些经验和建议能帮助大家更好地处理高并发场景下的数据处理问题。如果有更好的解决方案或建议,欢迎交流讨论!
希望这个回答对你有帮助!如果你有任何其他问题或需要进一步的详细信息,请告诉我。
单线程的V8无法负担太大的并发!
不见得吧。。。
“http连接队列已满"是指那边的连接?
1.如果是 GPS终端量 到 node 的,那是 node 有性能瓶颈了。(个人觉得可能性小)
- 如果是 node 发送数据到 tomcat 的http连接,那还是tomcat/oracle这边有问题,来不及处理造成积压。
有条件,建议单独测试下,比如node接收到数据后,暂时不发到tomcat,直接写到本地文件,看看能不能扛住,一步一步排查。
不好意思,看错了,GPS终端量 到 node 的是tcp,不是 http
如果tomcat这边实在处理不过来,node收到数据后先存文件,后面慢慢发,如果要实时性,就直接丢掉好了。
建议从node端到java那边做个队列吧,不要一收到tcp包就直接转发,而是收到TCP包放入队列,跑一个定时器定时去发,不知道产品需求这样是否还满足了
如果能不经tomcat转一道,而是从node直接入oracle库,是最好的了,除非… oracle 自己也扛不住这么大、这么实时的的数据插入量。
github 上有一些 oracle node 的模块,不过好像都不太活跃的样子,我也一直在找,郁闷~~
只能用oracle了的因为用到thine模式,外网->内网
可以考虑把Tomcat换做Jetty!
感觉需要加入内存数据库层或MQ做缓冲,nodejs内也可以做队列,但服务处理速度跟不上,堆积的数据肯定越来越大,nodejs超过1g可能出现内存已满的错误,如果是长时间速度跟不上应该考虑怎么提高后端速度吧。如果是瞬时处理不过来。缓冲一下就好了。
说的有道理,是oracle数据库处理跟不上,因为oracle还要进行位置分析要花费几百毫秒的时间。话说为什么点击回复都没反应呢??
你的网速慢吧
436062598
针对处理并发量大的数据,Node.js 是一个很好的选择,因为它基于事件驱动、非阻塞I/O模型,非常适合处理高并发场景。以下是一些优化和解决并发问题的经验分享:
示例代码:处理高并发TCP连接
const net = require('net');
// 创建TCP服务器
const server = net.createServer((socket) => {
socket.on('data', (data) => {
// 解析GPS数据
const parsedData = parseGPSData(data);
// 发送到HTTP服务
sendDataToService(parsedData);
});
socket.on('error', (err) => {
console.error('Socket error:', err);
});
});
server.listen(3000, () => {
console.log('Server listening on port 3000');
});
function parseGPSData(data) {
// 这里实现你的数据解析逻辑
return JSON.parse(data.toString());
}
async function sendDataToService(data) {
const options = {
hostname: 'localhost',
port: 3001,
path: '/gps-data',
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
};
return new Promise((resolve, reject) => {
const req = http.request(options, (res) => {
let body = '';
res.on('data', (chunk) => {
body += chunk;
});
res.on('end', () => {
resolve(body);
});
});
req.on('error', (err) => {
reject(err);
});
req.write(JSON.stringify(data));
req.end();
});
}
优化和解决并发问题的方法
-
使用集群模式: Node.js 支持多核CPU利用,可以使用
cluster
模块来创建多个子进程,每个子进程负责处理一部分连接。const cluster = require('cluster'); const numCPUs = require('os').cpus().length; if (cluster.isMaster) { for (let i = 0; i < numCPUs; i++) { cluster.fork(); } } else { // 子进程运行的代码 const net = require('net'); const server = net.createServer((socket) => { socket.on('data', (data) => { const parsedData = parseGPSData(data); sendDataToService(parsedData); }); }); server.listen(3000); }
-
限流和节流: 可以通过队列或缓冲机制限制数据的处理速度,防止数据库过载。
const queue = require('promise-queue'); const dataQueue = new queue(10, Infinity); // 最多10个任务并行 async function sendDataToService(data) { await dataQueue.add(() => sendHttpRequest(data)); } async function sendHttpRequest(data) { // 实现HTTP请求发送 }
-
异步处理: 使用
async/await
和Promise
来确保代码的异步执行不阻塞其他操作。
通过这些方法,可以显著提高Node.js应用在高并发情况下的性能和稳定性。希望这些经验对你有所帮助!