了解 NodeJS WebSocket 服务器的对象创建和垃圾收集

Joã*_*imo 3 garbage-collection v8 websocket node.js

我将nodejs 中的ws模块用于 Web 套接字服务器,代码的简化版本是这样的:

var WebSocketServer = require('ws').Server
var wss = new WebSocketServer({port: 9001});

wss.on('connection', function (ws) {

    // is the ws object created here ?

  ws.on('message', function (message) {
    if (message[0] === '+') {
        ws.name = message.substring(1);
        console.log(ws.name+' connected');
    }
  });

  ws.on('close', function () {
    console.log(ws.name+' disconnected');
    // Will this ws object be deleted ?
  });
});
Run Code Online (Sandbox Code Playgroud)

我想知道:

  • 在连接的每个事件上,是否创建了 ws 对象?
  • 每个连接的客户端中的一个对象是否会一直保留在 RAM 中,直到它被垃圾收集?

最重要的是:如果大量客户端断开连接并且 ws 对象一直闲置直到它们被垃圾收集,当垃圾收集发生时,我的服务器可能会被锁定很长一段时间,对吗?我是否应该解决将这些 ws 对象存储在另一个对象中的麻烦,以便我可以使用 delete 关键字并在收到关闭事件后立即删除它们?

如果我这样做,我可能会有点像这样:

var WebSocketServer = require('ws').Server
var wss = new WebSocketServer({port: 9001});

var websockets = {};

wss.on('connection', function (ws) {
  ws.on('message', function (message) {
    if (message[0] === '+') {
        ws.name = message.substring(1);
        websockets[ws.name] = ws; // Add to the object that stores ws objects
        console.log(ws.name+' connected');
    }
  });

  ws.on('close', function () {
    delete websockets[ws.name]; // Delete from the object
    console.log(ws.name+' disconnected');
  });
});
Run Code Online (Sandbox Code Playgroud)

那么,值得吗?我是否在第二个代码段中编写了更多垃圾收集友好代码?当垃圾收集发生时,它是否有助于避免长时间锁定?

更新:对不起,我刚刚意识到第二段代码是多么愚蠢。当我这样做时,我实际上是在复制对象的数量websockets[ws.name] = ws......但问题的第一部分仍然有效。

fre*_*ish 5

在连接的每个事件上,是否创建了 ws 对象?

是的。

每个连接的客户端中的一个对象是否会一直保留在 RAM 中,直到它被垃圾收集?

是的,每个JavaScript 对象都是如此。

我是否应该解决将这些 ws 对象存储在另一个对象中的麻烦,以便我可以使用 delete 关键字并在收到关闭事件后立即删除它们?

不。使用delete关键字不会释放您的内存。事实上,它什么都不做,只是删除了引用。考虑这个例子:

var x = { };
var y = { };
var z = { };
x.test = z;
y.test = z;
delete x.test;
Run Code Online (Sandbox Code Playgroud)

如您所见,x.test已删除(对象x不再具有.test属性 )但z根本没有删除,因为y持有对z.

您认为 WS 如何处理多个ws对象?它将它们存储在内部某个地方。如果您想删除ws对象,那么只需执行

ws.on('close', function () {
    delete ws;
});
Run Code Online (Sandbox Code Playgroud)

这将确保垃圾收集器在某个时刻收集ws。另一方面,我认为它WS已经在内部解决了这个问题,所以你根本不必担心它。

旁注:在 JavaScript 中没有办法触发垃圾收集器。不过不用担心。如果您达到内存限制,它将自行触发。

  • 实际上有一种方法可以在 NodeJS 中触发垃圾收集器:你只需要运行带有标志 --expose_gc 的节点来公开一个触发垃圾收集的 gc() 函数,并且因为你会这样做你也可以禁用空闲带有标志的垃圾收集 --nouse-idle-notification (3认同)