关于Node做Socket连接池遇到垃圾回收的问题
发布于 6 年前 作者 xivistudios 3744 次浏览 来自 问答

由于我大规模使用长连接,对于node这种异步回调的东东,我需要使用连接池,但是我在项目中遇到一个很坑的问题,我在全局对象里面申请了一个对象,专门用来以key, value的方式保存连接池,然后我对这个对象进行维护,测试的时候发现,连接经常断开,也没有任何错误抛出,我监控了很长时间,认为是V8把连接池里面的连接GC掉了,因为我是用的Socket.io,按理说,如果我自己的连接池被清理掉了,socket.io这个插件维护的连接也不会断开,找不出原因,严重怀疑V8的元凶,可能是内存溢出了QQ截图20170325022310.png

7 回复

不知道,楼下的告诉你

就不该用全局对象,node优势在于密集io,拿内存做存储或缓存是不靠谱的。node的gc有很多坑,我建议把你的全局对象换成redis来做,不仅避开了node各种gc问题,而且可以扩展。你现在的连接池,拿一个全局对象来搞,node是单进程模型,扩展性为0啊。。。

分享一个我曾经踩的坑吧,我曾尝试过用node内存对象充当缓存,我知道这样干不靠谱,但百度的server要申请redis集群很麻烦,成本也不低,当时的业务场景让我尝试性地做了这件事,怕leak,所以经过反复压测,我确认我的缓存池没有内存泄露,十几个node实例分别维护着各自的缓存对象,这样持续了几个小时,观察内存监控我确认缓存池触底,gc正常,进程没崩。隔了一夜之后的中午,突然出现奇怪的现象,eventloop似乎变得很慢,node向后端数据库请求的超时判断受到了巨大影响,随之造成顶在前面的nginx由于upstream重连及多层nginx的放大效应,疯狂地请求node,最终结果是node进程打爆,软件上的重启无效。。。联系op。。。硬重启。。。此后不再尝试类似的缓存,老老实实redis或memcache。。。

这个问题我研究了一段时间v8源码,没找到直接证据能够证明v8的高强度gc会直接影响eventloop,但gc造成进程假死的说法确实存在。我目前的怀疑依然是v8的gc产生了副作用致使eventloop变慢。如果有了解这方面的朋友欢迎讨论。

你socket没做鉴权?直接就能连接上?

GC都造成STW了,难道eventloop还不变慢么。

global不会被回收

回到顶部