[javascript] 멀티 코어 머신의 Node.js

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

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

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



답변

[ 이 게시물은 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) ...}

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


답변

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


답변

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

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

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


답변

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

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


답변

다중 노드는 보유한 모든 코어를 활용합니다.
한 번 봐 가지고 http://github.com/kriszyp/multi-node을 .

보다 간단한 요구를 위해 다른 포트 번호에서 여러 노드 사본을 시작하고로드 밸런서를 그 앞에 놓을 수 있습니다.


답변

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.
}

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


답변

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

같은 것을 추가

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

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

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

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