【问题标题】:how do node.js file descriptors work?node.js 文件描述符如何工作?
【发布时间】:2016-01-27 17:02:40
【问题描述】:

我正在尝试编写一个程序,该程序将所有足够大的文件用于 gzip,并使用 zlib 模块的 gzip 部分压缩它们,我遇到了与in this question 描述的相同错误,错误是 node.js用完文件描述符,因此无法打开任何其他文件。在同一个问题中,它描述了通过增加文件描述符的数量来修复它。尽管我遇到了几个我找不到答案的问题,但在尝试这样做时。

  1. 文件描述符是否在父进程和子进程之间共享?意思是我们可以通过为使用大量文件描述符的程序创建一个新的子进程来解决这个错误吗?子进程的类型重要吗? 罢工>
  2. 像 zlib 这样的进程使用多少个文​​件描述符?在我的程序中,我试图压缩 1695 个文件,但 673 个失败我知道每个文件至少有 2 个文件描述符(1 个用于 readStream,1 个用于 writeStream)但限制远高于此,所以 zlib 本身创建了多少?
  3. 有没有办法改变 node.js javascript 文件中的文件描述符限制?还是只能在外部更改?
  4. 可以从命令行参数更改限制,使其可以是特定于应用程序的吗?
  5. 是否可以监控当前正在使用的文件描述符数量?这可能会让您减慢创建新的读/写流调用的速度,从而允许旧进程完成释放文件描述符。最好是 node.js 本身的一种方式,以便可以轻松地将其集成到节点 javascript 文件中

更多示例目的是我的程序的代码

var errors=0;
function compressFile(file,type){
    if(type.indexOf('gzip')>=0){
        fs.stat(file,function(err,stat){
            if(!err){
                if(stat.size>1000){
                    var gzip=zlib.createGzip();
                    var compiled=fs.createReadStream(file,{autoclose:true}).on('error',function(err){
                        console.log(file,1);
                        //console.log(err);
                    });
                    var compressed=fs.createWriteStream(file+'.gz',{autoclose:true}).on('error',function(err){
                        console.log(file,2);
                        errors++
                        //console.log(err);
                        console.log(errors);
                    });
                    compiled.pipe(gzip).pipe(compressed);
                }
            }else{
                console.log(err);
            }
        });
    }else{
        console.log('not supported compression');
    }
}
function compressAll(){
    fs.readdir('./',function(err,files){
        if(err){
            console.log(err);
        }else{
            for(i=0;i<files.length;i++){
                var stat=fs.statSync('./'+files[i]);
                if(stat.isDirectory()){
                    var subfiles=fs.readdirSync(files[i]);
                    subfiles=subfiles.map(function(value){
                        return files[i]+'/' +value;
                    });
                    files.splice(i,1);
                    Array.prototype.push.apply(files,subfiles);
                    i--;
                }else if(stat.size<1000){
                    console.log(files[i],stat.size);
                    files.splice(i,1);
                    i--;
                }else if(path.parse(files[i]).ext==='.gz'){
                    files.splice(i,1);
                    i--;
                }else{
                    compressFile(files[i],compress);
                }
            }
            console.log(files.length);
        }
    });
}

正如我之前所说,我试图通过它运行 1695 个文件并收到 673 个错误,因此它在大约 1000 个压缩文件的地方用完了文件描述符

更新 根据我对文件描述符与操作系统的关系的新理解,我发现我的问题 1,3 和 4 不适用于 node.js,但我仍然想知道 2 和 5。zlib 使用了多少,是否有监控文件描述符的方法?

【问题讨论】:

  • 请注意,这与 NodeJS 无关。这是操作系统的事情。这可能会帮助您找到答案。
  • 它是特定于操作系统的,但 node.js 施加了自己的限制以防止文件描述符泄漏。所以我询问 node.js 对 os 文件描述符的使用
  • 是什么让您认为 Node 施加了自己的限制?
  • github.com/nodejs/node/blob/… 看下主题节点应该不会自动改变rlimits。
  • @Binvention:这描述了支持和反对节点忽略操作系统对文件描述符施加软限制的论点。这些限制仍然是操作系统限制。谷歌 ulimit 和 rlimit。它们不是特定于节点的。

标签: javascript node.js


【解决方案1】:

一般而言,您提出的问题似乎有些随机,因此您可能需要尝试了解更多有关文件描述符的一般信息。此外,Windows 本身没有文件描述符,因此任何关于文件描述符的内容实际上在 Windows 上都意味着其他内容。

但是,直接回答您的问题:

2) 如果您的意思是 node.js 内置的 zlib 类,那么根本不使用文件描述符。如果您的意思是一般地启动一个外部进程,那么默认情况下 node.js 会为每个标准输入、标准输出和标准错误创建一个管道。这意味着它会暂时创建 6 个文件描述符,但其中 3 个将被父进程关闭 - 因此每个外部进程有 3 个文件描述符。

5) 你可以通过fs.readdirSync("/proc/self/fd") 来查看unix 系统中进程的所有打开文件描述符。但是,由于您似乎在 Windows 上,这对您没有帮助,而且我不适合知道 node.js 是否在 Windows 上包装了一些可用的 API。

您编写的示例代码为每个压缩文件创建了两个文件描述符,仅此而已。解决方案不是将它们全部并行 gzip(无论如何这都非常低效),而是决定合理的并行度并仅并行运行那么多压缩。

【讨论】:

  • Gzip 和其他 zlib 函数通过流 api 运行,因此也有文件描述符 nodejs.org/dist/latest-v5.x/docs/api/…
  • 不,流式 API 完全在 node.js 内部实现 - 没有操作系统文件描述符。
  • 但是它使用操作系统的标准输入输出接口,需要文件描述符。
  • 不,不是,它只是node.js内部的一个可读流,实现了zlib提供的操作:zlib.net/manual.html
  • $ node -e 'var fs = require("fs"); var zlib = require("zlib"); var x = JSON.stringify(fs.readdirSync("/proc/self/fd")); var gzip = zlib.createGzip(); var y = JSON.stringify(fs.readdirSync("/proc/self/fd")); console.log(x == y);' 结果为true
猜你喜欢
  • 2011-10-28
  • 2011-04-28
  • 2011-01-14
  • 2023-03-09
  • 2017-12-15
  • 2022-01-03
  • 2020-09-20
  • 2011-06-18
相关资源
最近更新 更多