首页 > 解决方案 > 事件侦听器是否在 Node.js 中保留在内存中?

问题描述

在 Samer Buna 的以下文章中...

https://medium.freecodecamp.org/node-js-child-processes-everything-you-need-to-know-e69498fe970a

他谈到了child_process.fork在 Node.js 中的使用。在他的示例中(靠近底部),他有一个简单的 HTTP 服务器来侦听请求事件,当事件发生时,他使用child_process.fork创建进程来执行长计算,然后在完成后将消息发送回父级。为了返回子进程的结果,他注册了一个事件监听器,监听来自子进程的消息,然后返回响应。很直接。

一旦父进程收到子进程的消息并发送响应,compute.on事件监听器会发生什么?它是否存在于内存中(事件循环)?如果该示例处理了 100 个请求,即使请求已返回,是否还会有 100 个事件侦听器在监听?

计算.js

const longComputation = () => {
  let sum = 0;
  for (let i = 0; i < 1e9; i++) {
    sum += i;
  };
  return sum;
};

process.on('message', (msg) => {
  const sum = longComputation();
  process.send(sum);
});

服务器.js

const http = require('http');
const { fork } = require('child_process');

const server = http.createServer();

server.on('request', (req, res) => {
  if (req.url === '/compute') {
    const compute = fork('compute.js');
    compute.send('start');
    compute.on('message', sum => {
      res.end(`Sum is ${sum}`);
    });
  } else {
    res.end('Ok')
  }
});

server.listen(3000);

标签: javascriptnode.js

解决方案


事件侦听器会一直保存在内存中,直到它们所附加的 EventEmitter 被销毁。

对于您的代码,子进程及其事件侦听器永远不会被丢弃。当收到请求时,每次都会创建一个全新的子进程。请求回调完成后,对分叉进程的引用被垃圾回收,但子进程本身仍在后台运行,造成大量僵尸进程和内存泄漏。虽然,您的事件侦听器将持续存在。

更好的架构可能是在应用程序启动时启动一个子进程池(或者,如果您的负载较轻,则只启动一个进程),然后根据需要使用这些子进程来处理请求。


推荐阅读