Maison  >  Article  >  interface Web  >  À propos du module child_process dans node (tutoriel détaillé)

À propos du module child_process dans node (tutoriel détaillé)

亚连
亚连original
2018-06-09 16:23:511666parcourir

Cet article présente principalement les notes d'étude détaillées du module node child_process. Je vais les partager avec vous maintenant et leur donner une référence.

NodeJs est un langage à processus unique et ne peut pas créer plusieurs threads pour une exécution simultanée comme Java. Bien entendu, dans la plupart des cas, NodeJs ne nécessite pas d’exécution simultanée car il est piloté par les événements et ne bloque jamais. Mais un seul processus a également un problème, c'est-à-dire qu'il ne peut pas utiliser pleinement le mécanisme multicœur du processeur. Selon l'expérience précédente, vous pouvez utiliser pleinement le processeur multicœur en créant plusieurs processus et nœuds. utilise le module child_process pour créer et réaliser des opérations multi-processus.

Le module child_process donne au nœud la possibilité de créer des processus enfants à volonté. La documentation officielle du nœud donne quatre méthodes pour le module child_proces, qui sont en fait mappées au système d'exploitation pour créer des processus enfants. Mais pour les développeurs, les API de ces méthodes sont un peu différentes

child_process.exec(command[, options][, callback]) démarre le processus enfant pour exécuter la commande shell, et vous pouvez obtenir le script shell via le paramètre de rappel Résultat de l'exécution

child_process.execfile(file[, args][, options][, callback]) Différent du type exec, il n'exécute pas une commande shell mais un fichier exécutable

child_process.spawn(command[, args][, options]) exécute uniquement une commande shell et n'a pas besoin d'obtenir les résultats de l'exécution

child_process.fork(modulePath[, args][, options] ) peut être exécuté avec le fichier node .js, il n'est pas nécessaire d'obtenir les résultats de l'exécution. Le processus enfant qui sort du fork doit être un processus de nœud

Lors de la création de exec() et execfile(), vous pouvez spécifier l'attribut timeout pour définir le délai d'attente. Une fois le délai expiré, il sera supprimé.

Si vous utilisez execfile( ) pour exécuter le fichier exécutable, alors l'en-tête doit être #!/usr/bin/env node

Communication inter-processus

La communication entre le nœud et le processus enfant se fait à l'aide du mécanisme de canal IPC. Si le processus enfant est également un processus de nœud (utilisant fork), vous pouvez écouter l'événement de message et utiliser send() pour communiquer.

main.js

var cp = require('child_process');
//只有使用fork才可以使用message事件和send()方法
var n = cp.fork('./child.js');
n.on('message',function(m){
 console.log(m);
})

n.send({"message":"hello"});

child.js

var cp = require('child_process');
process.on('message',function(m){
 console.log(m);
})
process.send({"message":"hello I am child"})

Un canal IPC sera créé entre les processus parent et enfant L'événement de message et send(). utilisera le canal IPC pour communiquer.

Gérer le passage

Après avoir appris à créer un processus enfant, nous créons un service HTTP et démarrons plusieurs processus pour créer conjointement. utilisation complète du processeur multicœur.

worker.js

var http = require('http');
http.createServer(function(req,res){
 res.end('Hello,World');
 //监听随机端口
}).listen(Math.round((1+Math.random())*1000),'127.0.0.1');

main.js

var fork = require('child_process').fork;
var cpus = require('os').cpus();
for(var i=0;i<cpus.length;i++){
 fork(&#39;./worker.js&#39;);
}

Le code ci-dessus créera un nombre correspondant de processus fork en fonction du nombre de cœurs de votre processeur. Chaque processus écoute sur un port aléatoire pour fournir un service HTTP.

Ce qui précède complète un modèle de réplication maître-esclave typique Master-Worker. Il est utilisé pour le traitement parallèle des activités dans les applications distribuées et présente une bonne contraction et stabilité. Il convient de noter ici que la création d'un processus coûte cher et que le pilote d'événement à processus unique de nœud a de bonnes performances. Les multiples processus de fork dans cet exemple visent à utiliser pleinement le cœur du processeur, mais ne résolvent pas le problème de concurrence.

Un inconvénient de l'exemple ci-dessus est qu'il occupe trop de ports. effectué pour plusieurs processus enfants ? L'utilisation du même port pour fournir des services http au monde extérieur utilise uniquement ce port. Essayez de remplacer le numéro de port aléatoire ci-dessus par 8080. Au démarrage, vous constaterez que l'exception suivante est levée.

events.js:72
  throw er;//Unhandled &#39;error&#39; event
Error:listen EADDRINUSE
XXXX

lève une exception indiquant que le port est occupé, ce qui signifie qu'un seul travailleur.js peut écouter le port 8080, et les autres lèveront des exceptions.

Si vous souhaitez résoudre le problème de la fourniture d'un port vers le monde extérieur, vous pouvez vous référer à la méthode du proxy inverse nginx. Pour le processus maître, le port 80 est utilisé pour fournir des services au monde extérieur, tandis que pour le processus fork, un port aléatoire est utilisé lorsque le processus maître reçoit la demande, il la transmet au processus fork

. Pour le mode proxy que nous venons de mentionner, puisque le processus chaque fois qu'une connexion est reçue, un descripteur de fichier sera utilisé. Par conséquent, en mode proxy, le client se connecte au processus proxy, et le processus proxy se connecte ensuite au processus fork, qui utilisera deux descripteurs de fichiers. Le nombre de descripteurs de fichiers dans le système d'exploitation est limité. Afin de résoudre ce problème, le nœud introduit la fonction d'envoi de handles entre les processus.

Dans l'API de communication de processus IPC du nœud, le deuxième paramètre de send(message, [sendHandle]) est le handle.

Un handle est une référence qui identifie une ressource et contient le descripteur de fichier pointant vers l'objet. Le handle peut être utilisé pour décrire un objet socket, un socket UDP et un tube. L'envoi d'un handle au processus de travail par le processus principal signifie que lorsque le processus principal reçoit la demande de socket du client, il enverra directement le socket au socket. processus de travail sans avoir à interagir avec lui. Lorsque le processus de travail établit une connexion socket, le gaspillage de descripteurs de fichiers peut être résolu. Regardons l'exemple de code :

main.js

var cp = require(&#39;child_process&#39;);
var child = cp.fork(&#39;./child.js&#39;);
var server = require(&#39;net&#39;).createServer();
//监听客户端的连接
server.on(&#39;connection&#39;,function(socket){
 socket.end(&#39;handled by parent&#39;);
});
//启动监听8080端口
server.listen(8080,function(){
//给子进程发送TCP服务器(句柄)
 child.send(&#39;server&#39;,server);
});

child.js

process.on(&#39;message&#39;,function(m,server){
 if(m===&#39;server&#39;){
 server.on(&#39;connection&#39;,function(socket){
  socket.end(&#39;handle by child&#39;);
 });
 }
});

Vous pouvez le tester en utilisant telnet ou curl :

wang@wang ~/code/nodeStudy $ curl 192.168.10.104:8080
poignée par le parent
wang@wang ~/code/nodeStudy $ curl 192.168.10.104:8080
poignée par enfant
wang@ test Le résultat est que chaque connexion client peut être traitée par le processus parent ou par le processus enfant. Maintenant, nous essayons de fournir uniquement des services http, et afin de rendre le processus parent plus léger, nous laissons uniquement le processus parent transmettre le handle au processus enfant sans effectuer de traitement des requêtes :

main.js

child.js

Lors de l'exécution du code ci-dessus, la vérification de l'occupation du port 8080 donnera les résultats suivants :
var cp = require(&#39;child_process&#39;);
var child1 = cp.fork(&#39;./child.js&#39;);
var child2 = cp.fork(&#39;./child.js&#39;);
var child3 = cp.fork(&#39;./child.js&#39;);
var child4 = cp.fork(&#39;./child.js&#39;);
var server = require(&#39;net&#39;).createServer();
//父进程将接收到的请求分发给子进程
server.listen(8080,function(){
 child1.send(&#39;server&#39;,server);
 child2.send(&#39;server&#39;,server);
 child3.send(&#39;server&#39;,server);
 child4.send(&#39;server&#39;,server);
 //发送完句柄后关闭监听
 server.close();
});

 wang@wang ~/code/nodeStudy $ lsof -i:8080
COMMANDE  PID UTILISATEUR   FD   TYPE DEVICE SIZE/OFF NOM DU NŒUD
node    5120 wang   11u  IPv6  44561      0t0  TCP *:http-alt (ÉCOUTER)
nœud    5126 wang   11u  IPv6  44561      0t0  TCP *:http-alt (LISTEN)
node    5127 wang   11u  IPv6  44561      0t0  TCP *:http-alt (LISTEN)
node    5 133 wang   11u  IPv6  44561      0t0  TCP * :http-alt (ÉCOUTER)

运行curl查看结果:

wang@wang ~/code/nodeStudy $ curl 192.168.10.104:8080
Je suis un enfant.Id:5127
wang@wang ~/code/nodeStudy $ curl 192.168.10.104:8080
Je suis un enfant.Id:5133
wang@wang ~/code/nodeStudy $ curl 192.168.10.104:8080
Je suis child.Id:5120
wang@wang ~/code/nodeStudy $ curl 192.168.10.104:8080
Je suis enfant.Id:5126
wang@wang ~/code/nodeStudy $ curl 192.168.10.104 : 8080
Je suis un enfant.Id:5133
wang@wang ~/code/nodeStudy $ curl 192.168.10.104:8080
Je suis un enfant.Id:5126

上面是我整理给大家的,希望今后会对大家有帮助。

相关文章:

详解解读在vue项目中引入elementUI组件

vue-routerElementUI 🎜>

使用vue -routeur

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn