>  기사  >  웹 프론트엔드  >  노드의 child_process 모듈 정보(자세한 튜토리얼)

노드의 child_process 모듈 정보(자세한 튜토리얼)

亚连
亚连원래의
2018-06-09 16:23:511609검색

이 글은 주로 node child_process 모듈의 자세한 학습노트를 소개하고 있으니 참고용으로 올려보겠습니다.

NodeJs는 단일 프로세스 언어이며 Java와 같은 동시 실행을 위해 여러 스레드를 만들 수 없습니다. 물론 대부분의 경우 NodeJ는 이벤트 기반이고 차단되지 않기 때문에 동시 실행이 필요하지 않습니다. 그러나 단일 프로세스에도 문제가 있습니다. 즉, CPU의 멀티 코어 메커니즘을 최대한 활용할 수 없다는 것입니다. 이전 경험에 따르면 여러 프로세스를 생성하여 멀티 코어 CPU를 최대한 활용할 수 있으며 노드는 다음과 같습니다. 다중 프로세스 작업을 생성하고 완료하기 위해 child_process 모듈을 사용합니다.

child_process 모듈은 노드에 마음대로 하위 프로세스를 생성할 수 있는 기능을 제공합니다. 공식 노드 문서는 하위 프로세스를 생성하기 위해 운영 체제에 실제로 매핑되는 child_proces 모듈에 대한 네 가지 방법을 제공합니다. 하지만 개발자의 경우 이들 메소드의 API가 조금 다릅니다

child_process.exec(command[, options][, callback])는 자식 프로세스를 시작하여 쉘 명령을 실행하며, 다음을 통해 스크립트 쉘 실행 결과를 얻을 수 있습니다. 콜백 매개변수

child_process.execfile(file[, args][, options][, callback]) exec 유형과 달리 쉘 명령이 아닌 실행 파일을 실행합니다.

child_process.spawn(command[, args][ , options])는 쉘 명령만 실행하므로 실행 결과를 얻을 필요가 없습니다.

child_process.fork(modulePath[, args][, options])는 노드에서 실행되는 .js 파일을 사용할 수 있으며, 실행 결과를 얻어야 합니다. 포크에서 나오는 하위 프로세스는 노드 프로세스여야 합니다

exec() 및 execfile()이 생성되면 timeout 속성을 지정하여 시간 초과되면 종료됩니다

execfile()을 사용하여 실행 파일을 실행한 다음 헤더 부서는 #!/usr/bin/env여야 합니다. node

프로세스 간 통신

노드와 하위 프로세스 간의 통신은 IPC 파이프 메커니즘을 사용하여 완료됩니다. . 하위 프로세스도 노드 프로세스(fork 사용)인 경우 메시지 이벤트를 수신하고 send()를 사용하여 통신할 수 있습니다.

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

상위 프로세스와 하위 프로세스 사이에 IPC 채널이 생성됩니다. 메시지 이벤트와 send()는 IPC 채널을 사용하여 통신합니다.

전달 처리

자식 프로세스를 생성하는 방법을 배운 후 HTTP 서비스를 생성하고 여러 프로세스를 시작하여 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;);
}

위 코드는 CPU 코어 수에 따라 해당 개수의 포크 프로세스를 생성하고 각 프로세스는 임의의 포트를 수신하여 HTTP 서비스를 제공합니다.

위는 일반적인 마스터-워커 마스터-슬레이브 복제 모델을 완성합니다. 분산 애플리케이션에서 비즈니스의 병렬 처리에 사용되며 수축률과 안정성이 좋습니다. 여기서는 프로세스를 분기하는 데 비용이 많이 들고 노드 단일 프로세스 이벤트 드라이버의 성능이 좋다는 점에 유의해야 합니다. 이 예의 다중 포크 프로세스는 동시성 문제를 해결하기 위한 것이 아니라 CPU 코어를 최대한 활용하기 위한 것입니다.

위 예의 나쁜 점은 너무 많은 포트를 차지하므로 동일한 포트를 여러 용도로 사용할 수 있다는 것입니다. 자식 프로세스? 따라서 이 포트만 외부 세계에 http 서비스를 제공하는 데 사용됩니다. 위의 임의의 포트 번호를 8080으로 변경해 보십시오. 시작할 때 다음 예외가 발생하는 것을 확인할 수 있습니다.

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

는 포트가 사용 중이라는 예외를 발생시킵니다. 즉, 단 하나의 Worker.js만 포트 8080을 수신할 수 있고 나머지는 예외를 발생시킵니다.

외부 세계에 포트를 제공하는 문제를 해결하려면 nginx 역방향 프록시 방법을 참조할 수 있습니다. 마스터 프로세스의 경우 포트 80을 사용하여 외부 서비스를 제공하고, 포크 프로세스의 경우 마스터 프로세스가 요청을 받으면 이를 포크 프로세스로 전달합니다.

방금 언급한 프록시 모드의 경우, 프로세스가 연결을 수신할 때마다 하나의 파일 설명자가 사용되므로 프록시 모드에서는 클라이언트가 프록시 프로세스에 연결되고 프록시 프로세스는 포크 프로세스에 연결되며 파일 설명자 수는 2개가 사용됩니다. OS에서는 이 문제를 해결하기 위해 노드가 프로세스 간 핸들을 전송하는 기능을 도입합니다.

노드의 IPC 프로세스 통신 API에서 send(message, [sendHandle])의 두 번째 매개변수는 핸들입니다.

핸들은 리소스를 식별하는 참조이며 개체를 가리키는 파일 설명자를 포함합니다. 핸들은 소켓 개체, UDP 소켓 및 파이프를 설명하는 데 사용할 수 있습니다. 기본 프로세스가 작업자 프로세스에 핸들을 보내는 것은 기본 프로세스가 클라이언트의 소켓 요청을 받으면 소켓을 직접 보내는 것을 의미합니다. 작업자 프로세스와 상호 작용할 필요 없이 작업자 프로세스가 소켓 연결을 설정하면 파일 설명자의 낭비가 해결될 수 있습니다. 샘플 코드를 살펴보겠습니다:

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

텔넷이나 컬을 사용하여 테스트할 수 있습니다:

wang@wang ~/code/nodeStudy $ 컬 192.168.10.104:8080
handled by parent
wang@wang ~/code/nodeStudy $ 컬 192.168.10.104:8080
자녀가 처리
wang@wang ~/code/nodeStudy $ 컬 192.168.10.104:8080
부모가 처리
wang@wang ~/code/nodeStudy $ 컬 192.168.10.104:8080
handled by parent

테스트 결과는 각 클라이언트 연결이 상위 프로세스 또는 하위 프로세스에 의해 처리될 수 있다는 것입니다. 이제 우리는 http 서비스만 제공하려고 노력하고 있으며 상위 프로세스를 더 가볍게 만들기 위해 요청 처리를 수행하지 않고 상위 프로세스만 하위 프로세스에 핸들을 전달하도록 합니다.

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

위 코드를 실행했을 때, 이때 8080 포트 점유를 확인하면 다음과 같은 결과가 나옵니다.

wang@wang ~/code/nodeStudy $ lsof -i:8080
명령 PID 사용자 FD 유형 장치 크기/OFF 노드 이름
node 5120 wang 11u IPv6 44561 0t0 TCP *:http-alt (LISTEN)
no de 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)

컬 실행 결과 보기:

wang@wang ~/code/nodeStudy $ 컬 192.168.10.104:8080
나는 어린이입니다.ID:5127
wang@wang ~/code/nodeStudy $ 컬 192.168.10.104:8080
나는 어린이입니다. Id: 5133
wang@wang ~/code/nodeStudy $ 컬 192.168.10.104:8080
나는 어린이입니다.Id:5120
wang@wang ~/code/nodeStudy $ 컬 192.168.10.104:8080
나는 어린이입니다.ID: 5126
wang@wang ~/code/nodeStudy $ 컬 192.168.10.104:8080
나는 어린이입니다.ID:5133
wang@wang ~/code/nodeStudy $ 컬 192.168.10.104:8080
나는 어린이입니다.ID:5126

위에서 모든 사람을 위해 정리했습니다. 앞으로 모든 사람에게 도움이 되기를 바랍니다.

관련 기사:

vue 프로젝트에 elementUI 구성 요소를 도입하는 방법에 대한 자세한 설명

vue-router에서 ElementUI로 탐색을 구현하는 방법

vue에서 페이지 점프를 구현하고 원래 페이지 초기로 돌아가는 방법 position

vue-router를 사용하여 각 페이지의 제목 방법을 설정하는 방법

Vue.js에서 데이터를 표시할 때 페이지가 깜박이는 문제를 해결하는 방법

위 내용은 노드의 child_process 모듈 정보(자세한 튜토리얼)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.