멀티 코어 머신의 Node.js


606

Node.js를이 흥미로운 보이는, 하지만 뭔가 그리워한다 - Node.js를 단일 프로세스 및 스레드에서 실행 만 조정되지 않습니다?

그렇다면 멀티 코어 CPU 및 멀티 CPU 서버에 어떻게 확장 할 수 있습니까? 결국 단일 스레드 서버를 최대한 빨리 만드는 것이 좋지만로드가 많은 경우 여러 CPU를 사용하고 싶습니다. 응용 프로그램을 더 빠르게 만드는 것도 마찬가지입니다. 오늘날은 여러 CPU를 사용하고 작업을 병렬 처리하는 방식으로 보입니다.

Node.js는이 그림에 어떻게 맞습니까? 여러 인스턴스를 배포하려는 아이디어입니까?


4
Ryah가 노드에 내장 된 멀티 코어 지원을 포함시키는 것에 대해 진지해지기 시작한 것 같습니다 : github.com/joyent/node/commit/…
broofa

2
PM2 프로세스 관리자는 내부적으로 클러스터 모듈을 사용하여 NodeJS 앱을 사용 가능한 모든 코어로 확산합니다. github.com/Unitech/pm2
Unitech

@broofa, 이들은 실제 스레드가 아니며 하위 프로세스에는 공유 메모리가 없습니다. 또한 Java의 실제 스레딩 및 휘발성 정적 변수와 동등한 Nodejs무엇입니까?를 참조하십시오 . .
Pacerier

답변:


697

[ 이 게시물은 2012-09-02 현재 최신 상태입니다. ]

Node.js는 멀티 코어 머신에서 절대적으로 확장됩니다.

예. Node.js는 프로세스 당 하나의 스레드입니다. 이것은 매우 신중한 디자인 결정이며 잠금 의미론을 처리 할 필요가 없습니다. 이것에 동의하지 않는다면 아마 멀티 스레드 코드를 디버깅하는 것이 얼마나 어려운지 알지 못할 것입니다. Node.js 프로세스 모델에 대한 자세한 설명과 왜 이런 방식으로 작동하는지 (그리고 여러 스레드를 지원하지 않는 이유) 다른 게시물을 읽으십시오 .

16 코어 박스를 어떻게 활용합니까?

두 가지 방법:

  • 이미지 인코딩과 같은 대규모 컴퓨팅 작업의 경우 Node.js는 하위 프로세스를 시작하거나 추가 작업자 프로세스로 메시지를 보낼 수 있습니다. 이 디자인에서는 하나의 스레드가 이벤트 흐름을 관리하고 N 개의 프로세스가 많은 컴퓨팅 작업을 수행하고 다른 15 개의 CPU를 씹습니다.
  • 웹 서비스의 처리량을 조정하려면 하나의 상자에서 여러 개의 Node.js 서버를 코어 당 하나씩 실행하고 요청 트래픽을 분할해야합니다. 이는 탁월한 CPU 선호도를 제공하며 코어 수에 따라 처리량을 거의 선형으로 확장합니다.

웹 서비스의 처리량 확장

v6.0.X Node.js에는 클러스터 모듈 이 기본적으로 포함되어 있어 단일 포트에서 청취 할 수있는 여러 노드 워커를 쉽게 설정할 수 있습니다. 이것은 npm을 통해 사용 가능한 이전 learnboost "cluster"모듈과 동일하지 않습니다 .

if (cluster.isMaster) {
  // Fork workers.
  for (var i = 0; i < numCPUs; i++) {
    cluster.fork();
  }
} else {
  http.Server(function(req, res) { ... }).listen(8000);
}

노동자들은 새로운 연결을 수용하기 위해 경쟁 할 것이며, 가장 적은 부하의 프로세스가 이길 가능성이 높습니다. 그것은 잘 작동하며 멀티 코어 박스에서 처리량을 상당히 확장시킬 수 있습니다.

여러 코어를 관리하기에 충분한로드가있는 경우 몇 가지 추가 작업을 수행하려고합니다.

  1. Nginx 또는 Apache 와 같은 웹 프록시 뒤에서 Node.js 서비스를 실행하십시오 (오버로드 조건을 사용하여 상자를 완전히 중단시키지 않는 한), URL을 다시 쓰고 정적 컨텐츠를 제공하고 다른 서브 서비스를 프록시 할 수있는 연결 제한을 수행 할 수있는 것입니다.

  2. 작업자 프로세스를 주기적으로 재활용하십시오. 장기 실행 프로세스의 경우 작은 메모리 누수도 결국 더해집니다.

  3. 설정 로그 수집 / 모니터링


추신 : 다른 글 (이 글을 쓰는 시점에서 가장 높은 글)에 대한 의견에서 Aaron과 Christopher 사이에 토론이 있습니다. 그것에 대한 몇 가지 의견 :

  • 공유 소켓 모델은 여러 프로세스가 단일 포트에서 수신 대기하고 새로운 연결을 수락하도록 경쟁하는 데 매우 편리합니다. 개념적으로, 당신은 각 프로세스가 단일 연결 만 받아들이고 죽을 것이라는 심각한 경고와 함께 아파치 사전 아파치를 생각할 수 있습니다. Apache의 효율성 손실은 새 프로세스를 처리하는 오버 헤드로 소켓 작업과 관련이 없습니다.
  • Node.js의 경우 N 작업자가 단일 소켓에서 경쟁하게하는 것이 매우 합리적인 솔루션입니다. 대안은 Nginx와 같은 온 박스 프론트 엔드를 설정하고 개별 작업자에게 프록시 트래픽을 보내 새로운 연결을 할당하기 위해 작업자를 번갈아 사용하는 것입니다. 두 솔루션은 매우 유사한 성능 특성을 가지고 있습니다. 위에서 언급했듯이 Nginx (또는 대안)가 노드 서비스를 향하게하고 싶을 것이므로 선택은 실제로 다음과 같습니다.

공유 포트 : nginx (port 80) --> Node_workers x N (sharing port 3000 w/ Cluster)

vs

개별 포트 : nginx (port 80) --> {Node_worker (port 3000), Node_worker (port 3001), Node_worker (port 3002), Node_worker (port 3003) ...}

개별 포트 설정에 약간의 이점이있을 수 있지만 (프로세스 간 연결이 적고,보다 정교한로드 밸런싱 결정 등이있을 수 있음), 설정 작업이 더 많고 내장 클러스터 모듈이 낮습니다. 대부분의 사람들에게 적합한 복잡한 대안.


1
하나의 박스에서 다른 nodejs 기반 서비스를 실행하기위한 조언을 제공 할 수 있습니까? 예를 들어 하나의 서버가 있고 CpuCore1에서 myservice1.js를 실행하고 CpuCore2에서 myservice2.js를 실행하려고한다고 가정하십시오. 이것을 위해 클러스터를 사용할 수 있습니까? 아니면 복제 된 서비스를 만드는 데만 유용합니까?
UpTheCreek

6
당신은 그것에 대한 질문을 게시해야합니다! (이 의견을 첫 번째 답변으로 복사하겠습니다). 당신이하고 싶은 것은 실제로 정말 간단합니다. 실제로 "클러스터"는 필요하지 않으며 두 개의 다른 노드 서비스 만 실행하면됩니다. 두 개의 스크립트, 두 개의 프로세스, 두 개의 포트 예를 들어 serviceA는 3000에서 청취하고 serviceB는 3001에서 청취 할 수 있습니다. 이러한 각 서비스는 "클러스터"를 사용하여 1 명 이상의 근로자를두고 정기적으로 재활용 할 수 있습니다. 그런 다음 포트 80에서 수신 대기하도록 Nginx를 구성 할 수 있습니다. 들어오는 "호스트"헤더 및 / 또는 URL 경로에 기반한 올바른 서비스
Dave Dopson

1
감사. 이미 관련 질문을 게시했습니다. 내가 생각한 것을 거의 설명했지만 CPU 코어를 대상으로 지정하는 방법에 대해 잘 모르겠습니다 (영원히 무언가를 사용할 때).
UpTheCreek

큰 대답 도슨. 두 노드 프로세스가 동일한 시스템에서 서로 통신하도록하는 가장 좋은 방법은 무엇입니까? 같은 컴퓨터에있을 때 TCP보다 빠른 프로토콜이 있습니까?
winduptoy

1
@Serob_b-글쎄요. 여러 머신에서 Node.js 앱을 실행하는 것이 매우 일반적입니다. 필요한 라이브러리는 없습니다. 여러 머신에서 코드를 실행하고 이들 사이에로드를 분산하면됩니다. 소프트웨어가 확장되도록 상태를 설계합니다 (즉, 상태를 메모리에 유지하지 않고 일종의 외부 데이터 서비스에 저장).
Dave Dopson

45

한 가지 방법은 서버에서 node.js의 여러 인스턴스를 실행 한 다음로드 밸런서 (바람직하게는 nginx와 같은 비 블로킹 인스턴스)를 앞에 배치하는 것입니다.


36
node.js는 nginx만큼 빠릅니다. 원하는 경우 node.js 서버 앞에 node.js로드 밸런서를 넣을 수 있습니다. :)
mikeal

26
라이언은 특히 노드가 더 안정적이 될 때까지 이것을하지 말라고 말했습니다. 가장 좋은 방법은 노드 앞에서 nginx를 실행하는 것입니다.
resopollution

2
노드 앞의 nginx의 경우 메모리 내 대기열이있는 경우와 같은 특정 문제를 해결하지 못합니다. 2 개의 노드 인스턴스는 서로의 대기열에 액세스 할 수 없습니다.
resopollution

5
또한 nginx는 HTTP 1.1을 완전히 지원하지 않으므로 WebSockets와 같은 것을 프록시 할 수 없습니다.
ashchristopher

2
@ mikeal, resopollution-나는 Nginx쪽에 강력합니다. Node.js를 여러 번 하드 크래시했습니다 (스택 추적 없음, 그냥 죽습니다). 나는 Nginx를 추락 한 적이 없다. 즉시 사용 가능한 Nginx는 모든 종류의 정상 스로틀로 구성됩니다. 기본적으로 Node.js는 상자가 다운 될 때까지 기존 연결을 제공하는 것보다 새로운 연결을 계속 수락합니다 ... 예, 전체 상자; 스트레스 테스트 노드 (현재는 그렇게 일어나지 않아야 함)에 의해 CentOS5 상자에서 커널을 추락했습니다. 나는 조금 돌아 왔으며, LB 형 역할을 포함하여 Node의 밝은 미래를 보았습니다. 아직은 아니야
Dave Dopson

30

Ryan Dahl 지난 여름 Google 에서 한 기술 강연 에서이 질문에 답변했습니다 . "여러 노드 프로세스를 실행하고 적절한 통신 수단을 사용하십시오 (예 : sendmsg () 스타일 IPC 또는 기존 RPC)".

손을 더럽 히고 싶다면 spark2를 확인하십시오. Forever 모듈을 . 여러 노드 프로세스를 쉽게 생성 할 수 있습니다. 포트 공유 설정을 처리하므로 각각 동일한 포트에 대한 연결을 수락하고 프로세스가 종료 될 때 / 재시작 될 때 자동으로 재 생성 할 수 있습니다.

업데이트-10/11/11 : 노드 커뮤니티의 합의는 클러스터 가 이제 머신 당 여러 노드 인스턴스를 관리하는 데 선호되는 모듈 인 것 같습니다 . 영원히 볼 가치가 있습니다.


8
영원히와 클러스터는 매우 다른 일을합니다. 둘 다 사용할 수도 있습니다. 프로세스가 종료되면 영원히 다시 시작됩니다. 클러스터는 여러 작업자를 관리합니다. Forever를 사용하여 마스터 프로세스를 관리 할 수 ​​있습니다.
Dave Dopson

4
또한 learnboost 모듈은 Node v0.6.x에 구운 클러스터 버전으로 대체되었습니다 (경고 : API 표면이 다름)
Dave Dopson

@broofa Redis 또는 Memcache를 사용하여 프로세스간에 문자열 / 데이터 / 배열을 보내는 것보다 기본 IPC는 어떻게 비교됩니까? 어느 쪽이 더 빠를까요?
NiCk Newman

1
@broofa, IPC는 Java와 C가 할 수있는 실제 공유 메모리에 비해 엄청난 오버 헤드를 가지고 있습니다.
Pacerier

@Pacerier True, 그러나 공유 메모리는 여러 호스트에서 확장하는 데 필요한 매크로 문제를 해결하지 않고 단일 호스트의 컨텍스트에서 확장하는 방법 문제 만 해결합니다. 즉, 클라우드에서 실행하는 방법.
broofa

20

클러스터 모듈을 사용할 수 있습니다 . 이것을 확인 하십시오 .

var cluster = require('cluster');
var http = require('http');
var numCPUs = require('os').cpus().length;

if (cluster.isMaster) {
    // Fork workers.
    for (var i = 0; i < numCPUs; i++) {
        cluster.fork();
    }

    cluster.on('exit', function(worker, code, signal) {
        console.log('worker ' + worker.process.pid + ' died');
    });
} else {
    // Workers can share any TCP connection
    // In this case its a HTTP server
    http.createServer(function(req, res) {
        res.writeHead(200);
        res.end("hello world\n");
    }).listen(8000);
}


12

Node J는 CPU를 최대한 활용하기 위해 클러스터링을 지원합니다. 클러스터에서 클러스터를 실행하지 않으면 하드웨어 기능을 낭비하는 것일 수 있습니다.

Node.js의 클러스터링을 사용하면 동일한 서버 포트를 공유 할 수있는 별도의 프로세스를 만들 수 있습니다. 예를 들어, 포트 3000에서 하나의 HTTP 서버를 실행하는 경우 단일 프로세서 코어의 단일 스레드에서 실행되는 하나의 서버입니다.

아래 표시된 코드를 사용하면 응용 프로그램을 클러스터링 할 수 있습니다. 이 코드는 Node.js가 나타내는 공식 코드입니다.

var cluster = require('cluster');
var numCPUs = require('os').cpus().length;

if (cluster.isMaster) {
    // Fork workers.
    for (var i = 0; i < numCPUs; i++) {
        cluster.fork();
    }

    Object.keys(cluster.workers).forEach(function(id) {
        console.log("I am running with ID : " + cluster.workers[id].process.pid);
    });

    cluster.on('exit', function(worker, code, signal) {
        console.log('worker ' + worker.process.pid + ' died');
    });
} else {

    //Do further processing.
}

전체 튜토리얼 은이 기사를 확인하십시오.


11

위에서 언급했듯이 클러스터 는 모든 코어에서 앱을 확장하고로드 밸런싱합니다.

같은 것을 추가

cluster.on('exit', function () {
  cluster.fork();
});

실패한 근로자를 다시 시작합니다.

요즘 많은 사람들이 PM2 를 선호합니다 .PM2 는 클러스터링을 처리하고 멋진 모니터링 기능을 제공 합니다. .

그런 다음 클러스터링으로 실행되는 여러 머신 앞에 Nginx 또는 HAProxy를 추가하면 여러 수준의 페일 오버와 훨씬 높은로드 용량이 있습니다.


3
PM2는 프로덕션 용도로 적합합니다. 모니터링 도구는 앱의 메모리 문제를 해결하는 데 도움이되었습니다.
mbokil

7

향후 버전의 노드를 사용하면 프로세스를 분기하고 메시지를 전달할 수 있으며 Ryan은 파일 핸들러도 공유 할 수있는 방법을 찾고 싶다고 말했기 때문에 웹 워커 구현이 쉽지는 않습니다.

현재로서는 이것에 대한 쉬운 해결책은 없지만 아직 초기 단계이며 node는 내가 본 것 중 가장 빠르게 움직이는 오픈 소스 프로젝트 중 하나이므로 가까운 장래에 멋진 것을 기대하십시오.


7

Spark2는 이제 더 이상 유지 관리되지 않는 Spark를 기반으로합니다. 클러스터 는 후속 제품이며 CPU 코어 당 하나의 작업자 프로세스를 생성하고 죽은 작업자를 다시 생성하는 것과 같은 멋진 기능이 있습니다.


원래 질문과 많은 답변은 몇 달 전이며 노드가 너무 빨리 이동하여 클러스터에 대한 설명을 추가해 주셔서 감사합니다. 클러스터와 그 예제를 살펴본 후 노드 (또는 OP?)가 노드에 원하는 것과 정확히 같습니다. 감사합니다!
리야드 칼라

5

Node Worker 를 사용하여 기본 프로세스에서 간단한 방법으로 프로세스를 실행하고 있습니다. 우리가 공식적인 방법이 돌아 오기를 기다리는 동안 잘 작동하는 것 같습니다.


1
node worker example.js를 실행할 수없는 이유는 노드가 0.3.3 이전 버전입니다
guilin 桂林

5

이 블록의 새로운 아이는 LearnBoost의 "위"입니다 입니다.

"Zero-downtime reloads"를 제공하고 모든 세계의 최고를 제공하기 위해 여러 작업자 (기본적으로 CPU 수이지만 구성 가능)를 추가로 생성합니다.

새롭지 만 꽤 안정적 인 것 같습니다. 현재 프로젝트 중 하나에서 행복하게 사용하고 있습니다.


5

클러스터 모듈은 당신이 당신의 시스템의 모든 코어를 활용할 수 있습니다. 실제로 매우 유명한 프로세스 관리자 pm2를 사용하여 코드를 건드리지 않고 단 2 개의 명령으로이 기능을 활용할 수 있습니다 .

npm i -g pm2
pm2 start app.js -i max

4

os 와 함께 클러스터 모듈을 사용하여 여러 코어에서 node.js 애플리케이션을 실행할 수 있습니다.보유한 CPU 수를 감지하는 데 사용할 수있는 모듈 수 있습니다.

예를 들어 server백엔드에서 간단한 http 서버를 실행 하는 모듈이 있고 여러 CPU에 대해 실행하려고 한다고 가정 해 봅시다 .

// Dependencies.
const server = require('./lib/server'); // This is our custom server module.
const cluster = require('cluster');
const os = require('os');

 // If we're on the master thread start the forks.
if (cluster.isMaster) {
  // Fork the process.
  for (let i = 0; i < os.cpus().length; i++) {
    cluster.fork();
  }
} else {
  // If we're not on the master thread start the server.
  server.init();
}


0

데이터 처리와 같은 기능을 별도의 프로세스로 푸시 할 수 있도록 유닉스 소켓을 수신하는 여러 독립형 서버로 웹 서비스를 설계 할 수도 있습니다.

이것은 cgi 프로세스가 비즈니스 로직을 처리 한 다음 unix 소켓을 통해 데이터를 데이터베이스로 푸시하고 가져 오는 대부분의 scrpting / database 웹 서버 아키텍처와 유사합니다.

차이점은 데이터 처리가 포트에서 수신 대기하는 노드 웹 서버로 작성된다는 것입니다.

더 복잡하지만 궁극적으로 멀티 코어 개발이 필요한 곳입니다. 각 웹 요청에 대해 여러 구성 요소를 사용하는 다중 프로세스 아키텍처


0

각각 하나의 NodeJS 프로세스를 실행하는 여러 개의 상자 앞에 순수한 TCP로드 밸런서 (HAProxy)를 사용하여 NodeJS를 여러 개의 상자로 확장 할 수 있습니다.

모든 인스턴스간에 공유 할 공통된 지식이있는 경우 중앙 Redis 스토어 또는 이와 유사한 것을 사용하여 모든 프로세스 인스턴스 (예 : 모든 상자)에서 액세스 할 수 있습니다.


해당 서버에 단일 코어 CPU가없는 한 다른 CPU를 사용하지 않는 한 모든 CPU 용량을 사용하지는 않습니다.
UpTheCreek
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.