即使销毁套接字,Node.js的内存使用率仍然很高

我创build了一个简单的nodejs服务器和客户端。 他们通过15000个tcpsockets互相交互。

客户代码:

'use strict'; const net = require('net'); for (let i = 0; i < 15000; ++i) { let socket = new net.Socket(); socket.connect(6000, '127.0.0.1', () => { console.log('Connected'); socket.write('data to server'); }); socket.on('data', data => { console.log(data); }); socket.on('close', () => { console.log('Connection closed'); }); } 

服务器代码:

 'use strict'; const net = require('net'); let sockets = []; let server = net.createServer(socket => { socket.write('blabla from server'); socket.on('data', data => { console.log(data); }); sockets.push(socket); if (sockets.length >= 15000) { setTimeout(() => { console.log('cleanup start'); for (let socket of sockets) { socket.end(); socket.destroy(); socket.unref(); } console.log('cleaned up and ready'); }, 80000); } }); if (global.gc) { setInterval(() => { global.gc(); }, 15000); } setInterval(() => { console.log(process.memoryUsage()); }, 5000); server.listen(6000, '127.0.0.1'); 

他们发送和接收消息。 在创build套接字的过程中,内存使用率变高。 但是在销毁套接字之后,我期望内存使用率变低,这种情况不会发生。

你有一个完整的空值的数组。

 sockets.push(socket); if (sockets.length >= 15000) { // The length is never decreasing setTimeout(() => { for (let socket of sockets) { [...] socket = null; // Because you just null the value but the array has still the same length. } }, 80000); } 

看看这个例子:

 var arr=[]; setInterval(function(){ arr.push(null); }, 1); setInterval(() => { console.log(process.memoryUsage()); console.log(arr.length); // You will see the array is growing continously }, 5000); 

所以解决scheme是select一个不同的迭代数字和切片,他们键释放数组索引,而不是用另一个属性覆盖它。

但是,为什么你删除所有连接方面,如果这些正在使用或不。 您可以更好地在客户端断开连接销毁sockets。

 sockets.slice(index,1); 

好吧,我似乎find了解决办法。 Nodejscaching将来使用的Socket对象。 这里是更新的代码。

服务器代码:

 'use strict'; const net = require('net'); let sockets = []; let numberOfSockets = 2000; let server = net.createServer(socket => { sockets.push(socket); if (sockets.length >= numberOfSockets) { console.log(process.memoryUsage()); console.log('cleanup start'); for (let socket of sockets) { socket.end(); socket.destroy(); socket.unref(); } sockets = []; global.gc(); setTimeout(() => { console.log(process.memoryUsage()); }, 1000); console.log('cleaned up and ready'); } }); if (global.gc) { setInterval(() => { global.gc(); }, 15000); } server.listen(6000, '127.0.0.1'); 

客户代码:

 'use strict'; const net = require('net'); let numberOfClosedSockets = 0; let numberOfSockets = 2000; function test() { for (let i = 0; i < numberOfSockets; ++i) { let socket = new net.Socket(); socket.connect(6000, '127.0.0.1', () => { console.log('Connected'); }); socket.on('data', data => { console.log(data); }); socket.on('close', () => { console.log('Connection closed ' + numberOfClosedSockets); numberOfClosedSockets++; if (numberOfClosedSockets >= numberOfSockets) { numberOfClosedSockets = 0; setTimeout(() => { test(); }, 2000); } socket.destroy(); socket.unref(); }); } } test(); 

在这个例子中,客户端在第一组套接字被销毁之后创build新套接字。 它一遍又一遍地做。 如果你看内存使用情况,它不会增加,所以没有内存泄漏。

github问题链接