Nodejs 基于TCP的服务器用PM2运行后资源暴涨
Nodejs 基于TCP的服务器用PM2运行后资源暴涨
主要实现的是一个聊天登陆功能的服务器,原来用forever运行没看到什么资源占用,如下
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
20558 root 20 0 758m 60m 5760 S 3.0 0.4 0:15.91 node
用了pm2启动并查看内存资源,差不多10个小时内存飙升到1.5g,cpu持续在8%平均,本来以为代码的memory leak,大量找资料,然后改写代码**(其实还是没找到哪里会memoryleak,只是把一些回调函数从临时改成成员函数,把收发socket数据的用户业务逻辑对象改成了资源池可复用,尽量减少创建新的buffer,不过buffer的创建不可避免因为要解决粘包问题)**
做了这些后,一点也没好效果啊,然后重新改用forever运行就又没这么变态的占用。 我没用cluster就是单进程跑的。 大家有谁有这方面经验么,反正用pm2的web检测看就是内存几秒涨一点,非常快
Nodejs 基于TCP的服务器用PM2运行后资源暴涨
背景
主要实现的是一个聊天登录功能的服务器。使用forever
运行时,没有观察到明显的资源占用。但是切换到PM2
运行后,发现内存资源迅速增长,CPU占用也持续较高。
现象描述
-
使用
forever
运行时:PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 20558 root 20 0 758m 60m 5760 S 3.0 0.4 0:15.91 node
-
使用
PM2
运行后:- 10小时内内存从几百MB增长到1.5GB。
- CPU持续在8%左右波动。
PM2
的Web界面显示内存每几秒钟增长一次,增长速度非常快。
尝试的优化措施
- 把一些回调函数从临时函数改为成员函数。
- 将收发socket数据的用户业务逻辑对象改成了资源池可复用。
- 尽量减少创建新的
Buffer
对象,但由于粘包问题,仍然需要创建新的Buffer
对象。
问题分析
经过上述优化措施后,资源占用依然很高,因此怀疑可能是PM2
本身或配置问题导致的内存泄漏。
解决方案
-
检查PM2配置:
- PM2默认配置可能不适合某些应用,可以尝试调整配置。
- 示例配置文件:
{ "apps": [ { "name": "chat-server", "script": "./server.js", "max_memory_restart": "1G", "instances": 1, "exec_mode": "fork" } ] }
-
增加垃圾回收频率:
- 可以通过修改Node.js参数来增加垃圾回收的频率。
- 示例启动命令:
pm2 start server.js --node-args="--max-old-space-size=4096 --expose-gc" --watch
-
使用
cluster
模式:- 单进程模式可能会导致资源占用过高,可以尝试使用
cluster
模式来提高性能和稳定性。 - 示例代码:
const cluster = require('cluster'); const os = require('os'); if (cluster.isMaster) { for (let i = 0; i < os.cpus().length; i++) { cluster.fork(); } } else { // TCP Server code here const net = require('net'); const server = net.createServer((socket) => { socket.on('data', (data) => { console.log(`Received data: ${data.toString()}`); socket.write(data); }); }); server.listen(3000, () => { console.log('Server is listening on port 3000'); }); }
- 单进程模式可能会导致资源占用过高,可以尝试使用
-
监控和调试:
- 使用工具如
memwatch-next
、heapdump
等来监控内存使用情况。 - 示例代码:
const memwatch = require('memwatch-next'); memwatch.on('stats', function(stats) { console.log(stats); });
- 使用工具如
通过以上措施,可以有效降低资源占用,并提高服务器的稳定性和性能。如果问题依然存在,建议进一步深入分析代码和系统配置。
根据你的描述,使用PM2运行Node.js TCP服务器时,发现内存占用异常增加。这种情况可能与PM2的运行机制或程序内部某些未被注意到的地方有关。这里有一些可能的原因和建议:
-
PM2缓存机制:PM2有自身的缓存机制,可能会导致内存占用异常增加。你可以尝试使用
pm2 flush
清除缓存。 -
内存泄漏检查:
- 使用工具如
memwatch-next
来检测内存泄漏。 - 确保所有事件监听器都被正确移除,特别是在处理TCP连接时。
- 避免全局变量的滥用,尤其是那些引用了大量数据的对象。
- 使用工具如
-
资源池优化:你已经提到对资源池进行了一些优化,确保对象池中的对象不会保存状态,以避免累积数据。
-
使用弱引用:如果需要保留某些对象引用但又不想阻止垃圾回收,可以考虑使用
weak
模块来管理这些引用。 -
日志分析:增加详细的日志记录,观察在内存增加时哪些操作频繁发生。
-
PM2配置调整:
- 尝试调整PM2的参数,如
--max-memory-restart
来自动重启内存超标的进程。 - 使用
pm2 start app.js --max_memory_restore 1G
限制内存增长。
- 尝试调整PM2的参数,如
示例代码片段(用于检测内存泄漏):
const memwatch = require('memwatch-next');
memwatch.on('leak', (info) => {
console.error('Memory Leak Detected:', info);
});
// 在合适的位置添加监听器移除逻辑
server.on('connection', (socket) => {
socket.on('data', (data) => {
// 处理数据
});
socket.on('end', () => {
// 移除监听器
socket.removeAllListeners();
});
});
以上建议希望能帮助你解决问题。如果内存泄漏仍然存在,可能需要进一步详细检查代码逻辑。