Node.js 流 API 泄​​漏

Posted

技术标签:

【中文标题】Node.js 流 API 泄​​漏【英文标题】:Node.js Stream API leak 【发布时间】:2013-12-25 06:56:28 【问题描述】:

在玩节点流时,我注意到几乎每个教程都教授以下内容:

// Get Google's home page.
require('http').get("http://www.google.com/", function(response) 
  // The callback provides the response readable stream.
  // Then, we open our output text stream.
  var outStream = require('fs').createWriteStream("out.txt");

  // Pipe the input to the output, which writes the file.
  response.pipe(outStream);
);

但在我看来,这是一段相当危险的代码。如果文件流在某个时候抛出异常会发生什么?我认为文件流可能会泄漏内存,因为根据文档,文件流显然没有关闭。

我应该关心吗?在我看来 node.js 流应该处理情况......

【问题讨论】:

【参考方案1】:

排除 Node 的 VM 中的任何错误,如果在打开流后出现中断操作的异常,我希望最终在垃圾收集期间 VM 会检测到没有任何内容引用流并收集它,从而处理与其关联的资源。

所以我不会称之为“泄漏”。

仍然可能存在与处理异常或不关闭流相关的问题。例如,在 Unix 类型的系统上,当创建与磁盘上的文件相对应的流时,会使用文件描述符。一个进程一次可以打开多少个文件描述符是有限制的。因此,如果一个没有显式关闭其流的进程设法让其中许多未关闭,以至于在下一次垃圾回收之前达到文件描述符限制,它将崩溃。

【讨论】:

这基本上是我的想法。因此,如果目标流失败(例外情况),通过管道传输到目标流的源流不会关闭。 它不会在异常发生时立即关闭,但垃圾收集应该到达并关闭它。【参考方案2】:

为避免文件描述符泄漏,还需要:

var outStream = require('fs').createWriteStream("out.txt");

// Add this to ensure that the out.txt's file descriptor is closed in case of error.
response.on('error', function(err) 
  outStream.end();
);

// Pipe the input to the output, which writes the file.
response.pipe(outStream);

另一个未记录的方法是outStream.destroy(),它也会关闭描述符,但似乎首选outStream.end()

【讨论】:

以上是关于Node.js 流 API 泄​​漏的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 node.js 顺序读取 csv 文件(使用流 API)

在 Node.js 上从 Web Audio API 播放 PCM 流

Node篇

关于 Node.js Stream API 的用法概述

哪些库可用于使用 WritableStream 和 Node.js Readable 等标准流 API 将数据从浏览器流式传输到服务器? [关闭]

在 node.js 服务器上使用 supertest/superagent 读取响应输出缓冲区/流