Heim  >  Artikel  >  Web-Frontend  >  Über das child_process-Modul im Knoten (ausführliches Tutorial)

Über das child_process-Modul im Knoten (ausführliches Tutorial)

亚连
亚连Original
2018-06-09 16:23:511677Durchsuche

In diesem Artikel werden hauptsächlich die detaillierten Studiennotizen des Moduls node child_process vorgestellt. Ich werde sie jetzt mit Ihnen teilen und ihnen eine Referenz geben.

NodeJs ist eine Einzelprozesssprache und kann nicht wie Java mehrere Threads für die gleichzeitige Ausführung erstellen. Natürlich erfordert NodeJs in den meisten Fällen keine gleichzeitige Ausführung, da es ereignisgesteuert ist und niemals blockiert. Ein einzelner Prozess hat jedoch auch das Problem, dass er den Multi-Core-Mechanismus der CPU nicht vollständig nutzen kann. Nach bisherigen Erfahrungen können mehrere Prozesse erstellt werden, um die Multi-Core-CPU vollständig auszunutzen, und Node verwendet zum Erstellen das Modul child_process und vollständige Multiprozessoperationen.

Das Modul „child_process“ gibt Node die Möglichkeit, nach Belieben untergeordnete Prozesse zu erstellen. Das offizielle Dokument von „node“ gibt vier Methoden für das Modul „child_proces“ an, mit denen tatsächlich untergeordnete Prozesse erstellt werden. Für Entwickler sind die APIs dieser Methoden jedoch etwas anders.

child_process.exec(command[, options][, callback]) startet den untergeordneten Prozess, um den Shell-Befehl auszuführen, und Sie können die Skript-Shell abrufen über den Callback-Parameter Ausführungsergebnis

child_process.execfile(file[, args][, options][, callback]) Anders als der exec-Typ führt er keinen Shell-Befehl, sondern eine ausführbare Datei aus

child_process.spawn(command[, args][, Optionen]) führt nur einen Shell-Befehl aus und muss die Ausführungsergebnisse nicht abrufen

child_process.fork(modulePath[, args][, Optionen] ) kann mit der .js-Datei des Knotens ausgeführt werden, es ist nicht erforderlich, Ausführungsergebnisse abzurufen. Der aus der Verzweigung kommende untergeordnete Prozess muss ein Knotenprozess sein

Beim Erstellen von exec() und execfile() können Sie das Timeout-Attribut angeben, um das Timeout festzulegen. Sobald es abläuft, wird es beendet

Wenn Sie execfile( ) verwenden, um die ausführbare Datei auszuführen, muss der Header #!/usr/bin/env node sein

Interprozesskommunikation

Die Kommunikation zwischen dem Knoten und dem untergeordneten Prozess erfolgt über den IPC-Pipe-Mechanismus. Wenn der untergeordnete Prozess auch ein Knotenprozess ist (mithilfe von Fork), können Sie das Nachrichtenereignis abhören und mit send() kommunizieren.

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"})

Ein IPC-Kanal wird zwischen den übergeordneten und untergeordneten Prozessen erstellt, und das Nachrichtenereignis und send() verwenden die IPC-Kanal zur Kommunikation.

Übergabe verarbeiten

Nachdem wir gelernt haben, wie man einen untergeordneten Prozess erstellt, erstellen wir einen HTTP-Dienst und starten mehrere Prozesse, um gemeinsam den vollen Nutzen daraus zu ziehen Multi-Core-CPU.

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;);
}

Der obige Code erstellt eine entsprechende Anzahl von Fork-Prozessen basierend auf der Anzahl Ihrer CPU-Kerne, und jeder Prozess lauscht an einen zufälligen Port, um HTTP-Dienste bereitzustellen.

Das Obige vervollständigt ein typisches Master-Worker-Master-Slave-Replikationsmodell. Es wird für die parallele Geschäftsverarbeitung in verteilten Anwendungen verwendet und weist eine gute Schrumpfung und Stabilität auf. Hierbei ist zu beachten, dass das Forken eines Prozesses teuer ist und der Knoten-Einzelprozess-Ereignistreiber eine gute Leistung aufweist. Die mehreren Fork-Prozesse in diesem Beispiel sollen den CPU-Kern voll ausnutzen, aber nicht das Parallelitätsproblem lösen.

Eine schlechte Sache an dem obigen Beispiel ist, dass es zu viele Ports belegt, das kann also sein Wird dies für mehrere untergeordnete Prozesse getan? Wenn Sie denselben Port verwenden, um der Außenwelt HTTP-Dienste bereitzustellen, wird nur dieser Port verwendet. Versuchen Sie, die oben genannte zufällige Portnummer auf 8080 zu ändern. Beim Start werden Sie feststellen, dass die folgende Ausnahme ausgelöst wird.

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

löst eine Ausnahme aus, wenn der Port belegt ist. Dies bedeutet, dass nur ein worker.js Port 8080 abhören kann und der Rest eine Ausnahme auslöst.

Wenn Sie das Problem der Bereitstellung eines Ports für die Außenwelt lösen möchten, können Sie auf die Nginx-Reverse-Proxy-Methode zurückgreifen. Für den Master-Prozess wird Port 80 verwendet, um Dienste für die Außenwelt bereitzustellen, während für den Fork-Prozess ein zufälliger Port verwendet wird. Wenn der Master-Prozess die Anfrage empfängt, leitet er sie an den Fork-Prozess weiter

Für den gerade erwähnten Proxy-Modus wird, da der Prozess jeweils eine Verbindung empfängt, ein Dateideskriptor verwendet. Daher stellt der Client im Proxy-Modus eine Verbindung zum Proxy-Prozess her und der Proxy-Prozess stellt dann eine Verbindung zum Fork-Prozess her. Die Anzahl der Dateideskriptoren im Betriebssystem ist begrenzt. Für dieses Problem führt Node die Funktion zum Senden von Handles zwischen Prozessen ein.

In der IPC-Prozesskommunikations-API des Knotens ist der zweite Parameter von send(message, [sendHandle]) das Handle.

Ein Handle ist eine Referenz, die eine Ressource identifiziert und den Dateideskriptor enthält, der auf das Objekt verweist. Das Handle kann zum Beschreiben eines Socket-Objekts, eines UDP-Sockets und einer Pipe verwendet werden. Das Senden eines Handles an den Arbeitsprozess durch den Hauptprozess bedeutet, dass der Hauptprozess den Socket direkt an den sendet, wenn er die Socket-Anfrage des Clients empfängt Worker-Prozess ohne weiteren Kontakt Wenn der Worker-Prozess eine Socket-Verbindung herstellt, kann die Verschwendung von Dateideskriptoren behoben werden. Schauen wir uns den Beispielcode an:

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;);
 });
 }
});

Sie können es mit Telnet oder Curl testen:

wang@ wang ~ /code/nodeStudy $ curl 192.168.10.104:8080
Handle durch Elternteil
wang@wang ~/code/nodeStudy $ curl 192.168.10.104:8080
Handle durch Kind
wang@wang ~ /code /nodeStudy $ curl 192.168.10.104:8080
vom übergeordneten Element verwaltet
wang@wang ~/code/nodeStudy $ curl 192.168.10.104:8080
vom übergeordneten Element verwaltet

Das Testergebnis ist jedes Mal Bei Clientverbindungen können sie vom übergeordneten Prozess oder vom untergeordneten Prozess verarbeitet werden. Jetzt versuchen wir, nur einen HTTP-Dienst bereitzustellen, und um den übergeordneten Prozess einfacher zu gestalten, lassen wir den übergeordneten Prozess nur das Handle an den untergeordneten Prozess übergeben, ohne eine Anforderungsverarbeitung durchzuführen:

main.js

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();
});

child. js

var http = require(&#39;http&#39;);
var serverInChild = http.createServer(function(req,res){
 res.end(&#39;I am child.Id:&#39;+process.pid);
});
//子进程收到父进程传递的句柄(即客户端与服务器的socket连接对象)
process.on(&#39;message&#39;,function(m,serverInParent){
 if(m===&#39;server&#39;){
 //处理与客户端的连接
 serverInParent.on(&#39;connection&#39;,function(socket){
  //交给http服务来处理
  serverInChild.emit(&#39;connection&#39;,socket);
 });
 }
});

Wenn Sie den obigen Code ausführen, führt die Überprüfung der 8080-Portbelegung zu den folgenden Ergebnissen:

 wang@wang ~/code/nodeStudy $ lsof -i:8080
COMMAND  PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
node    5120 wang   11u  IPv6  44561      0t0  TCP *:http-alt (LISTEN)
node    5126 wang   11u  IPv6  44561      0t0  TCP *:http-alt (LISTEN)
node    5127 wang   11u  IPv6  44561      0t0  TCP *:http-alt (LISTEN)
node   . 5133 wang   11u  IPv6  44561      0t0  TCP * :http-alt (LISTEN)

运行curl查看结果:

wang@wang ~/code/nodeStudy $ curl 192.168.10.104:8080
Ich bin child.Id:5127
wang@wang ~/code/nodeStudy $ curl 192.168.10.104:8080
Ich bin child.Id:5133
wang@wang ~/code/nodeStudy $ curl 192.168.10.104:8080
Ich bin child.Id:5120
wang@wang ~/code/nodeStudy $ curl 192.168.10.104:8080
Ich bin child.Id:5126
wang@wang ~/code/nodeStudy $ curl 192.168.10.104: 8080
Ich bin kind.Id:5133
wang@wang ~/code/nodeStudy $ curl 192.168.10.104:8080
Ich bin kind.Id:5126

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

相关文章:

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

在vue-router中配合ElementUI如何实现导航

在vue中如何实现页面跳转后返回原页面初始位置

使用vue -router如何设置每个页面的title方法

如何解决Vue.js显示数据的时,页面闪现

Das obige ist der detaillierte Inhalt vonÜber das child_process-Modul im Knoten (ausführliches Tutorial). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn