프로그래밍 언어/NODE JS

cluster

· 코딩마이데이

cluster 모듈은 기본적으로 싱글 프로세스로 동작하는 노드가 CPU 코어를 모두 사용할 수 있게 해주는 모듈입니다. 포트를 공유하는 노드 프로세스를 여러 개 둘 수도 있으므로, 요청이 많이 들어왔을 때 병렬로 실행된 서버의 개수만큼 요청이 분산되게 할 수 있습니다. 서버에 무리가 덜 가게 되는 셈입니다.

cluster 모듈을 설정하여 코어 하나당 노드 프로세스 하나가 돌아가게 할 수 있습니다. 코어를 하나만 사용할 때에 비해 성능이 개선됩니다. 하지만 장점만 있는 것은 아니며, 메모리를 공유하기 못하는 등의 단점도 있습니다. 세션을 메모리에 저장하는 경우 문제가 될 수 있습니다. 이는 레디스 등의 서버를 도입하여 해결할 수 있습니다.

 

cluster.js

const cluster = require("cluster");
const http = require("http");
const numCPUs = require("os").cpus().length;

if (cluster.isMaster) {
  console.log(`마스터 프로세스 아이디: ${process.pid}`);
  // CPU 개수만큼 워커를 생산
  for (let i = 0; i < numCPUs; i += 1) {
    cluster.fork();
  }
  // 워커가 종료되었을 때
  cluster.on("exit", (worker, code, signal) => {
    console.log(`${worker.process.pid}번 워커가 종료되었습니다.`);
    console.log("code", code, "signal", signal);
  });
} else {
  // 워커들이 포트에서 대기
  http
    .createServer((req, res) => {
      res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
      res.write("<h1>Hello Node!</h1>");
      res.end("<p>Hello Cluster!</p>");
    })
    .listen(8086);

  console.log(`${process.pid}번 워커 실행`);
}

 

클러스터에는 마스터 프로세스와 워커 프로세스가 있습니다. 마스터 프로세스는 CPU 개수만큼 워커 프로세스를 만들고, 8086번 포트에서 대기합니다. 요청이 들어오면 만들어진 워커 프로세스에 요청을 분배합니다.

클러스터링

 

워커 프로세스가 실질적인 일을 하는 프로세스입니다.코드를 다음과 같이 수정합니다.

 

cluster.js

const cluster = require("cluster");
const http = require("http");
const numCPUs = require("os").cpus().length;

if (cluster.isMaster) {
  console.log(`마스터 프로세스 아이디: ${process.pid}`);
  // CPU 개수만큼 워커를 생산
  for (let i = 0; i < numCPUs; i += 1) {
    cluster.fork();
  }
  // 워커가 종료되었을 때
  cluster.on("exit", (worker, code, signal) => {
    console.log(`${worker.process.pid}번 워커가 종료되었습니다.`);
    console.log("code", code, "signal", signal);
  });
} else {
  // 워커들이 포트에서 대기
  http
    .createServer((req, res) => {
      res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
      res.write("<h1>Hello Node!</h1>");
      res.end("<p>Hello Cluster!</p>");
      setTimeout(() => {
        // 워커가 존재하는지 확인하기 위해 1초마다 강제 종료
        process.exit();
      }, 1000);
    })
    .listen(8086);

  console.log(`${process.pid}번 워커 실행`);
}

 

요청이 들어올 때마다  1초 후에 서버가 종료되도록 했습니다. 이제 서버를 실행합니다. process.pid는 실행할 때마다 달라집니다. 각각 자신의 코어 개수에 맞게 워커가 실행되는지 확인해보세요.

콘솔

$ node cluster
마스터 프로세스 아이디: 15552
980번 워커 실행
12544번 워커 실행
27428번 워커 실행
25940번 워커 실행
4520번 워커 실행
6440번 워커 실행
22016번 워커 실행
27304번 워커 실행

 

http://localhost:8086에 접속하면 1초 후 콘솔에 워커가 종료되었다는 메시지가 뜹니다. 여섯 번의 새로고침을 하면 모든 워커가 종료되어 서버가 응답하지 않습니다.

20960번 워커가 종료되었습니다.
code 0 signal null
24284번 워커가 종료되었습니다.
code 0 signal null
11444번 워커가 종료되었습니다.
code 0 signal null
21152번 워커가 종료되었습니다.
code 0 signal null
5972번 워커가 종료되었습니다.
code 0 signal null
21984번 워커가 종료되었습니다.
code 0 signal null

 

코드(code)는 process.exit의 인수로 넣어준 코드가 출력되고, 신호(signal)는 존재하는 경우 프로세스를 종료한 진호의 이름이 출력됩니다.워커 프로세스가 존재하기에 여섯 번까지는 오류가 발생해도 서버가 정상 작동할 수 있다는 뜻입니다. 종료된 워커를 다시 켜면 오류가 발생해도 계속 버틸 수 있습니다.

 

cluster.js

const cluster = require("cluster");
const http = require("http");
const numCPUs = require("os").cpus().length;

if (cluster.isMaster) {
  console.log(`마스터 프로세스 아이디: ${process.pid}`);
  // CPU 개수만큼 워커를 생산
  for (let i = 0; i < numCPUs; i += 1) {
    cluster.fork();
  }
  // 워커가 종료되었을 때
  cluster.on("exit", (worker, code, signal) => {
    console.log(`${worker.process.pid}번 워커가 종료되었습니다.`);
    console.log("code", code, "signal", signal);
    cluster.fork();
  });
} else {
  // 워커들이 포트에서 대기
  http
    .createServer((req, res) => {
      res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
      res.write("<h1>Hello Node!</h1>");
      res.end("<p>Hello Cluster!</p>");
      setTimeout(() => {
        // 워커가 존재하는지 확인하기 위해 1초마다 강제 종료
        process.exit();
      }, 1000);
    })
    .listen(8086);

  console.log(`${process.pid}번 워커 실행`);
}

 

콘솔

15472번 워커가 종료되었습니다.
code 0 signal null
20216번 워커 실행
20216번 워커가 종료되었습니다.
code 0 signal null
21884번 워커 실행

 

 

 

 

 

 

 

 

 

 

 

'프로그래밍 언어 > NODE JS' 카테고리의 다른 글

패키지 버전 이해하기  (0) 2025.06.04
npm 알아보기 & package.json으로 패키지 관리하기  (1) 2025.06.01
https와 http2  (0) 2025.05.26
쿠키와 세션 이해하기  (1) 2025.05.23
REST와 라우팅 사용하기  (0) 2025.05.19