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('./worker.js'); }
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 'error' 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('child_process'); var child = cp.fork('./child.js'); var server = require('net').createServer(); //监听客户端的连接 server.on('connection',function(socket){ socket.end('handled by parent'); }); //启动监听8080端口 server.listen(8080,function(){ //给子进程发送TCP服务器(句柄) child.send('server',server); });
child.js
process.on('message',function(m,server){ if(m==='server'){ server.on('connection',function(socket){ socket.end('handle by child'); }); } });
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('child_process'); var child1 = cp.fork('./child.js'); var child2 = cp.fork('./child.js'); var child3 = cp.fork('./child.js'); var child4 = cp.fork('./child.js'); var server = require('net').createServer(); //父进程将接收到的请求分发给子进程 server.listen(8080,function(){ child1.send('server',server); child2.send('server',server); child3.send('server',server); child4.send('server',server); //发送完句柄后关闭监听 server.close(); });
child. js
var http = require('http'); var serverInChild = http.createServer(function(req,res){ res.end('I am child.Id:'+process.pid); }); //子进程收到父进程传递的句柄(即客户端与服务器的socket连接对象) process.on('message',function(m,serverInParent){ if(m==='server'){ //处理与客户端的连接 serverInParent.on('connection',function(socket){ //交给http服务来处理 serverInChild.emit('connection',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
上面是我整理给大家的,希望今后会对大家有帮助.
相关文章:
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!