Salut à tous :)

J'aimerais savoir s'il y a un moyen de déporter une tâche en background sur NodeJS ?
Je m'explique : J'ai un script qui top 100% du CPU du serveur à certains moments (plus de 10 000 000 de lignes à agréger), du coup j'aimerais déporter ce processus dans un processus enfant et distinct afin d'éviter de bloquer (enfin ralentir à mort plutôt) le serveur pendant ce temps, mais je ne trouve pas de moyen 'simple' de le faire.

Donc si vous avez des solutions ou des outils à me proposer, je suis preneur.

Merci.

12 réponses


betaWeb
Auteur
Réponse acceptée

J'ai fait différemment du coup : j'ai créé une nouvelle VM sur laquelle je déporte les traitements lourds et/ou longs (via une simple requête HTTP, avec la lib node-rest-client), cela évite d'impacter la VM de l'app principale. Je suis conscient que cette solution ne peut pas être implémentée partout, cela étant, si on peut le faire, il ne faut pas hésiter.

Salut,

Si 100% du CPU est pris, ça ne va rien changer si tu le mets dans un autre processus, non ?

betaWeb
Auteur

@tleb Beh disons qu'en le déportant dans un process child, ça permet au système de gérer les ressources allouées à chaque process, du coup essayer d'avoir du 50-50 ou au moins du 75-25 quoi ^^

betaWeb
Auteur

@tleb J'ai essayé mais pas moyen de le faire fonctionner.. je n'arrive pas à faire communiquer le process master avec le child.

Tu peux utiliser,

var child = require('child_process').fork('./child', args);

Si tu veux communiquer avec le processus parent tu utilises process.send(code); dans le processus child et tu écoutes avec

  child.on('message', function(message) {
    console.log(message)
  });

dans le processus parent.
Quand le processus child se termine, cette event est déclenché dans le processus parent

  child.on('close', function(code, signal) {
    console.log('Child process ' + child.pid + ' exited with code ' + code);
  });

Tu peux voir la doc pour d'autres events

betaWeb
Auteur

Salut @sizo0,

Merci pour tes conseils, c'est exactement ce que j'ai fait.
Mais en fait j'ai l'impression que le process est kill juste après avoir été créé car je ne le vois pas dans ma liste de process node (j'utilise htop) :/

Il est peut-être kill puisqu'il n'y a rien à exécuter.

Tu peux me montrer le code parent et le code child.

betaWeb
Auteur

master :

try {
    var invoiceChildProcess = fork('./renderInvoice.js');
} catch (err) {
    Utils.err(err, 'INVOICING::EXPLORE - INIT INVOICE CHILD PROCESS ERR');
}

try {
    invoiceChildProcess.send({billingData: billingData});
} catch (err) {
    Utils.err(err, 'INVOICING::EXPLORE - SEND DATA TO INVOICE CHILD PROCESS ERR');
}

invoiceChildProcess.on('uncaughtException', function (err) {
    Utils.err(err.message + "\n" + err.stack);
});

invoiceChildProcess.on('message', function (inv) {
    Utils.log('Receive invoice child process data :: ' + JSON.stringify(m), 'INVOICING::EXPLORE - RENDER INVOICE INTO CHILD PROCESS');
});

J'ai effacé le child, mais c'était un truc comme ça :

process.on('message', function (data) {
   // code à exécuter
   process.send('done');
});

Normalement le child ne doit pas être kill. Essaye de lancer cette commande pour voir s'il est vraiment kill

watch -n 1 -d  "ps aux | grep [n]ode"

Pour la fonction send, il faut un string en argument. Essaye donc de faire un JSON.stringify.
Je ne comprends pas non plus pk tu mets des try { } catch { } un peu partout.

Je te mets le code ci-dessous pour l'essayer et voir s'il marche pour toi.
Code parent.

var child_process = require('child_process');

var child = child_process.fork('./child');

send();

child.on('message', function (message) {
  console.log(message);
  setTimeout(function () {
    send();
  }, 1000);
});

child.on('close', function (code, signal) {
  console.log('Child process' + child.pid + 'exited with code ' + code);
});

function send() {
  child.send('message from parent');
}

Code child

process.on('message', function (message) {
  console.log(message);
  process.send('message from child');
});
betaWeb
Auteur

Les try catch c'est normal.
Ok merci je vais essayer ça :)

Salut si tu veux actuellement je check un peu les process node tu peux regarder ce que j'ai mis sur mon github
https://github.com/dgpgdev/processcom
ça permet de creer un ou plusieurs process enfants et de communiquer avec. Si ça peut t'aider