269 votes

noeud et erreur: EMFILE, trop de fichiers ouverts

Pour quelques jours, j'ai cherché une solution de travail à une erreur

Error: EMFILE, too many open files

Il semble que beaucoup de gens ont le même problème. La réponse habituelle consiste à augmenter le nombre de descripteurs de fichiers. Donc, j'ai essayé ceci:

sysctl -w kern.maxfiles=20480,

La valeur par défaut est 10240. C'est un peu étrange à mes yeux, parce que le nombre de fichiers que je suis de manutention dans le répertoire est sous 10240. Plus étrange encore, je continue de recevoir le même message d'erreur après j'ai augmenté le nombre de descripteurs de fichiers.

Deuxième question:

Après plusieurs recherches j'ai trouvé un travail pour le "trop de fichiers ouverts" problème:

var requestBatches = {};
function batchingReadFile(filename, callback) {
  // First check to see if there is already a batch
  if (requestBatches.hasOwnProperty(filename)) {
    requestBatches[filename].push(callback);
    return;
  }

  // Otherwise start a new one and make a real request
  var batch = requestBatches[filename] = [callback];
  FS.readFile(filename, onRealRead);

  // Flush out the batch on complete
  function onRealRead() {
    delete requestBatches[filename];
    for (var i = 0, l = batch.length; i < l; i++) {
      batch[i].apply(null, arguments);
    }
  }
}

function printFile(file){
    console.log(file);
}

dir = "/Users/xaver/Downloads/xaver/xxx/xxx/"

var files = fs.readdirSync(dir);

for (i in files){
    filename = dir + files[i];
    console.log(filename);
    batchingReadFile(filename, printFile);

Malheureusement, j'ai encore recevoir le même message d'erreur. Quel est le problème avec ce code?

Une dernière question (je suis nouveau sur le javascript et le nœud), je suis en train de développer un site web application avec beaucoup de demandes pour environ 5000 utilisateurs quotidiens. J'ai de nombreuses années d'expérience dans programmation avec d'autres langages comme python et java. donc, au départ, je pensais à développer cette application avec django ou jouer au cadre. Puis j'ai découvert nœud et je dois dire que l'idée de la non-blocage I/O modèle est vraiment beau, séduisant, et surtout très rapide!

Mais ce genre de problèmes qui dois-je m'attendre avec noeud? Est-ce une production prouvé serveur web? Quelles sont vos expériences?

120voto

blak3r Points 5096

Pour quand gracieux-fs ne fonctionne pas... ou vous voulez juste de comprendre d'où vient la fuite vient de. À suivre ce processus.

(par exemple, gracieux-fs ne va pas résoudre votre wagon si votre problème est avec les sockets.)

À partir de Mon Blog l'Article: http://www.blakerobertson.com/devlog/2014/1/11/how-to-determine-whats-causing-error-connect-emfile-nodejs.html

Comment Isoler

Cette commande affiche le nombre de handles ouverts pour nodejs processus:

lsof -i -n -P | grep nodejs

COMMAND     PID    USER   FD   TYPE    DEVICE SIZE/OFF NODE NAME
...
nodejs    12211    root 1012u  IPv4 151317015      0t0  TCP 10.101.42.209:40371->54.236.3.170:80 (ESTABLISHED)
nodejs    12211    root 1013u  IPv4 151279902      0t0  TCP 10.101.42.209:43656->54.236.3.172:80 (ESTABLISHED)
nodejs    12211    root 1014u  IPv4 151317016      0t0  TCP 10.101.42.209:34450->54.236.3.168:80 (ESTABLISHED)
nodejs    12211    root 1015u  IPv4 151289728      0t0  TCP 10.101.42.209:52691->54.236.3.173:80 (ESTABLISHED)
nodejs    12211    root 1016u  IPv4 151305607      0t0  TCP 10.101.42.209:47707->54.236.3.172:80 (ESTABLISHED)
nodejs    12211    root 1017u  IPv4 151289730      0t0  TCP 10.101.42.209:45423->54.236.3.171:80 (ESTABLISHED)
nodejs    12211    root 1018u  IPv4 151289731      0t0  TCP 10.101.42.209:36090->54.236.3.170:80 (ESTABLISHED)
nodejs    12211    root 1019u  IPv4 151314874      0t0  TCP 10.101.42.209:49176->54.236.3.172:80 (ESTABLISHED)
nodejs    12211    root 1020u  IPv4 151289768      0t0  TCP 10.101.42.209:45427->54.236.3.171:80 (ESTABLISHED)
nodejs    12211    root 1021u  IPv4 151289769      0t0  TCP 10.101.42.209:36094->54.236.3.170:80 (ESTABLISHED)
nodejs    12211    root 1022u  IPv4 151279903      0t0  TCP 10.101.42.209:43836->54.236.3.171:80 (ESTABLISHED)
nodejs    12211    root 1023u  IPv4 151281403      0t0  TCP 10.101.42.209:43930->54.236.3.172:80 (ESTABLISHED)
....

Avis: 1023u (dernière ligne) - c'est du 1024 descripteur de fichier qui est la valeur maximale par défaut.

Maintenant, Regardez la dernière colonne. Qui indique les ressources est ouvert. Vous verrez probablement un certain nombre de lignes avec le même nom de la ressource. Espérons que maintenant vous indique où chercher dans votre code pour la fuite.

Si vous ne savez pas plusieurs nœud de processus, de recherche premier processus qui a pid 12111. Qui vais vous dire le processus.

Dans mon cas ci-dessus, j'ai remarqué qu'il y avait un tas de très similaire Adresses IP. Ils étaient tous 54.236.3.### En faisant l'adresse ip de recherches, a été en mesure de déterminer, dans mon cas, c'était pubnub liés.

Référence De La Commande

Utilisez cette syntaxe pour déterminer combien de poignées de s'ouvrir...

Pour obtenir le nombre de fichiers ouverts pour un certain pid

J'ai utilisé cette commande pour vérifier le nombre de fichiers qui ont été ouverts après divers événements dans mon application.

lsof -i -n -P | grep "8465" | wc -l

# lsof -i -n -P | grep "nodejs.*8465" | wc -l
28
# lsof -i -n -P | grep "nodejs.*8465" | wc -l
31
# lsof -i -n -P | grep "nodejs.*8465" | wc -l
34

Quel est votre processus de limite?

ulimit -a

La ligne que vous voulez ressembler à ceci: open files (-n) 1024

84voto

Meryn Stol Points 4099

L'utilisation du module graceful-fs d'Isaac Schlueter (mainteneur de noeud.js) est probablement la solution la plus appropriée. Il effectue un recul progressif si un fichier EMFILE est rencontré. Il peut être utilisé en remplacement immédiat du module intégré fs .

10voto

Trey Griffith Points 31

J'ai rencontré ce problème aujourd'hui et, ne trouvant pas de bonne solution, j'ai créé un module pour le résoudre. J'ai été inspiré par l'extrait de @ fbartho, mais je voulais éviter de remplacer le module fs.

Le module que j'ai écrit est Filequeue , et vous l'utilisez exactement comme fs:

 var Filequeue = require('filequeue');
var fq = new Filequeue(200); // max number of files to open at once

fq.readdir('/Users/xaver/Downloads/xaver/xxx/xxx/', function(err, files) {
    if(err) {
        throw err;
    }
    files.forEach(function(file) {
        fq.readFile('/Users/xaver/Downloads/xaver/xxx/xxx/' + file, function(err, data) {
            // do something here
        }
    });
});
 

10voto

Tim P. Points 131

Votre préparation à plusieurs fichiers à la fois. Node lit les fichiers en mode asynchrone, vous devez donc les lire tous à la fois. essayez de mettre en commun votre lecture de fichiers. Vous ne voulez vraiment pas lire 10240 à la fois. Un, vous avez une limite de mémoire de 1 Go avec noeud. lol vient d'écrire ceci pour vous voir si cela fonctionne. https://gist.github.com/1659615

 var fs = require('fs')
var events = require('events')
var util = require('util')
var path = require('path')

var FsPool = module.exports = function(dir) {
    events.EventEmitter.call(this)
    this.dir = dir;
    this.files = [];
    this.active = [];
    this.threads = 1;
    this.on('run', this.runQuta.bind(this))
};
// So will act like an event emitter
util.inherits(FsPool, events.EventEmitter);

FsPool.prototype.runQuta = function() {
    if(this.files.length === 0 && this.active.length === 0) {
        return this.emit('done');
    }
    if(this.active.length < this.threads) {
        var name = this.files.shift()

        this.active.push(name)
        var fileName = path.join(this.dir, name);
        var self = this;
        fs.stat(fileName, function(err, stats) {
            if(err)
                throw err;
            if(stats.isFile()) {
                fs.readFile(fileName, function(err, data) {
                    if(err)
                        throw err;
                    self.active.splice(self.active.indexOf(name), 1)
                    self.emit('file', name, data);
                    self.emit('run');

                });
            } else {
                self.active.splice(self.active.indexOf(name), 1)
                self.emit('dir', name);
                self.emit('run');
            }
        });
    }
    return this
};
FsPool.prototype.init = function() {
    var dir = this.dir;
    var self = this;
    fs.readdir(dir, function(err, files) {
        if(err)
            throw err;
        self.files = files
        self.emit('run');
    })
    return this
};
var fsPool = new FsPool(__dirname)

fsPool.on('file', function(fileName, fileData) {
    console.log('file name: ' + fileName)
    console.log('file data: ', fileData.toString('utf8'))

})
fsPool.on('dir', function(dirName) {
    console.log('dir name: ' + dirName)

})
fsPool.on('done', function() {
    console.log('done')
});
fsPool.init()
 

4voto

fbartho Points 174

Je viens juste de finir d'écrire un petit bout de code pour résoudre ce problème moi-même. Toutes les autres solutions semblent beaucoup trop lourdes et vous obligent à changer la structure de votre programme.

Cette solution bloque uniquement les appels fs.readFile ou fs.writeFile, de sorte qu’il n’ya plus qu’un nombre défini en vol à un moment donné.

 // Queuing reads and writes, so your nodejs script doesn't overwhelm system limits catastrophically
global.maxFilesInFlight = 100; // Set this value to some number safeish for your system
var origRead = fs.readFile;
var origWrite = fs.writeFile;

var activeCount = 0;
var pending = [];

var wrapCallback = function(cb){
    return function(){
        activeCount--;
        cb.apply(this,Array.prototype.slice.call(arguments));
        if (activeCount < global.maxFilesInFlight && pending.length){
            console.log("Processing Pending read/write");
            pending.shift()();
        }
    };
};
fs.readFile = function(){
    var args = Array.prototype.slice.call(arguments);
    if (activeCount < global.maxFilesInFlight){
        if (args[1] instanceof Function){
            args[1] = wrapCallback(args[1]);
        } else if (args[2] instanceof Function) {
            args[2] = wrapCallback(args[2]);
        }
        activeCount++;
        origRead.apply(fs,args);
    } else {
        console.log("Delaying read:",args[0]);
        pending.push(function(){
            fs.readFile.apply(fs,args);
        });
    }
};

fs.writeFile = function(){
    var args = Array.prototype.slice.call(arguments);
    if (activeCount < global.maxFilesInFlight){
        if (args[1] instanceof Function){
            args[1] = wrapCallback(args[1]);
        } else if (args[2] instanceof Function) {
            args[2] = wrapCallback(args[2]);
        }
        activeCount++;
        origWrite.apply(fs,args);
    } else {
        console.log("Delaying write:",args[0]);
        pending.push(function(){
            fs.writeFile.apply(fs,args);
        });
    }
};
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X