我正在處理物聯網應用程序,客戶端每2秒向服務器發送生物潛在信息。客戶端每2秒發送一個包含400行數據的CSV文件。我的服務器上運行着一個Socket.IO websocket服務器,它從每個客戶端捕獲這些信息。一旦捕獲到這些信息,服務器必須每2秒將這400條記錄推送到一個mysql數據庫中。儘管只要客戶端數量很小,這種方式就可以很好地工作,但隨着客戶端數量的增長,服務器開始拋出「進程內存異常」。NodeJS - 處理內存不足100個併發連接
以下是接收到異常:
<--- Last few GCs --->
98522 ms: Mark-sweep 1397.1 (1457.9) -> 1397.1 (1457.9) MB, 1522.7/0 ms [allocation failure] [GC in old space requested].
100059 ms: Mark-sweep 1397.1 (1457.9) -> 1397.0 (1457.9) MB, 1536.9/0 ms [allocation failure] [GC in old space requested].
101579 ms: Mark-sweep 1397.0 (1457.9) -> 1397.0 (1457.9) MB, 1519.9/0 ms [last resort gc].
103097 ms: Mark-sweep 1397.0 (1457.9) -> 1397.0 (1457.9) MB, 1517.9/0 ms [last resort gc].
<--- JS stacktrace --->
==== JS stack trace =========================================
Security context: 0x35cc9bbb4629 <JS Object>
2: format [/xxxx/node_modules/mysql/node_modules/sqlstring/lib/SqlString.js:~73] [pc=0x6991adfdf6f] (this=0x349863632099 <an Object with map 0x209c9c99fbd1>,sql=0x2dca2e10a4c9 <String[84]: Insert into rent_66 (sample_id,sample_time, data_1,data_2,data_3) values ? >,values=0x356da3596b9 <JS Array[1]>,stringifyObjects=0x35cc9bb04251 <false>,timeZone=0x303eff...
FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - process out of memory
Aborted
下面是我的服務器代碼:
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var mysql = require('mysql');
var conn = mysql.createConnection({
host: '<host>',
user: '<user>',
password: '<password>',
database: '<db>',
debug: false,
});
conn.connect();
io.on('connection', function (socket){
console.log('connection');
var finalArray = []
socket.on('data_to_save', function (from, msg) {
var str_arr = msg.split("\n");
var id = str_arr[1];
var timestamp = str_arr[0];
var data = str_arr.splice(2);
finalArray = [];
var dataPoint = [];
data.forEach(function(value){
dataPoint = value.split(",");
if(dataPoint[0]!=''){
finalArray.push([dataPoint[0],1,dataPoint[1],dataPoint[2],dataPoint[3]]);
finalArray.push([dataPoint[0],1,dataPoint[4],dataPoint[5],dataPoint[5]]);
}
});
var sql = "Insert into rent_"+id+" (sample_id,sample_time, channel_1,channel_2,channel_3) values ? ";
var query = conn.query (sql, [finalArray],function(err,result){
if(err)
console.log(err);
else
console.log(result);
});
conn.commit();
console.log('MSG from ' + str_arr[1] + ' ' + str_arr[0]);
});
});
http.listen(9000, function() {
console.log('listening on *:9000');
});
我能得到服務器處理100個併發連接後,我開始接收過程內存不足例外。在引入數據庫插入之前,服務器將簡單地將csv作爲文件存儲在磁盤上。通過該設置,服務器能夠處理1200+個併發連接。
根據互聯網上可用的信息,看起來像數據庫插入查詢(這是異步的)在內存中保存400行數組,直到插入通過。因此,隨着客戶端數量的增長,服務器的內存足跡會增加,從而最終導致內存不足。
我確實經歷了許多有關--max_old_space_size
在互聯網上提出的建議,我不確定這是一個長期的解決方案。另外,我不確定我應該在什麼基礎上決定應該在此提及的價值。
另外,我已經經歷了關於異步實用程序模塊的建議。但是,串行插入數據可能會在客戶端插入數據的時間與服務器將此數據保存到數據庫之間引入巨大的延遲。
我已經圍繞這個問題繞了很多次。有沒有辦法服務器可以處理來自1000多個併發客戶端的信息,並將這些數據以最小延遲保存到Mysql數據庫中。我在這裏遇到了一個路障,並且對這個方向的任何幫助都非常感激。
我不知道這是如何進入你的代碼,但在這個引號是不合法的Javascript:'socket.on('data_to_save',...)'。 – jfriend00
我不是MySQL的專家,要麼是一個好的解決方案可能來自更好的配置,或者我會建議去一個更輕量級的DB系統,例如MongoDB。 – Pac0
我首先註釋掉你的數據庫代碼,看看你是否可以處理傳入的消息。如果你能處理得很好,那麼問題出在你的DB代碼上(可能是內存或資源泄漏)。 – jfriend00