cluster를 통해 cpu의 갯수만큼워커 프로세스를 늘려보자

YOUNGJOO-YOON·2021년 12월 1일
0

node.js

목록 보기
3/3

cluster는 하나의 마스터 프로세스가 있고 워커 프로세스를 가지게 하여
노드에 가해지는 요청을 분산시켜준다.

6개의 코어가 있는 CPU의 경우를 생각해보면
1번 CPU는 마스터 프로세스로 일을 나누어 주는 역할을 한다.

나머지 5개의 CPU는 실질적인 node의 요청을 처리하게 되는데 하나의 CPU로 부하를 처리하는 것보다는 하드웨어의 자원을 보다 적극적으로 사용하는 형태를 가지게 되므로 부하가 늘어나게 되었다면 사용해보자.


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

const log = console.log;
if (cluster.isMaster) { // Node 16버전에서 deprecated되었다. 대체로 cluster.isPrimary를 사용하자
  log('master process id = ', process.pid);
  for (let i = 0; i < numCPUs; i += 1) {
    cluster.fork(); // cluster.fork([env])
    /** 
    *cluster.fork([env])#
Added in: v0.6.0
env <Object> Key/value pairs to add to worker process environment.
Returns: <cluster.Worker>
Spawn a new worker process.

This can only be called from the primary process.
master process에서 실행시킬 수 있고 인자로 env
    */
  }
  cluster.on('exit', (worker, code, signal) => {
    log(`${worker.process.pid} worker exit`);
    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 Cluster!</h1>');
      res.end('<p>Hello Cluster!</p>');
      setTimeout(() => {
        process.exit(1);
      }, 1000);
    })
    .listen(8086);

  console.log(`${process.pid}`);
}

node.js 교과서의 코드를 참고하였습니다.

추가로 cluster에 대해 알아본 결과 msg 시스템이 있어서 가져왔습니다.


const cluster = require('cluster');
const http = require('http');
const { cpus } = require('os');
const process = require('process');

if (cluster.isPrimary) {
  let numReqs = 0;
  setInterval(() => {
    console.log(`numReqs = ${numReqs}`);
  }, 1000);

  function messageHandler(msg) {
    if (msg.cmd && msg.cmd === 'notifyRequest') {
      numReqs += 1;
    }
  }

  const numCPUs = cpus().length;
  for (let i = 0; i < numCPUs; i++) {
    cluster.fork();
  }
  for (const id in cluster.workers) {
    cluster.workers[id].on('message', messageHandler);
  }
} else {
  http
    .Server((req, res) => {
      res.writeHead(200);
      res.end('hello world! \n');

      process.send({ cmd: 'notifyRequest' });
    })
    .listen(8212);
}

추측입니다

cluster를 통해 생성한 workers들에게 on method로 message event를 주고 콜백함수로 messageHandler를 넘겨줍니다.

primary process는 요청을 받아 worker에게 넘겨 일을 처리합니다.
worker는 일을 받아 일을 모두 완료하고 process.send method를 통해 값을 primary에게 전달하는데요

  for (const id in cluster.workers) {
    cluster.workers[id].on('message', messageHandler);
  }

cluster.workers의 message를 listen하고 있는 primary 함수는 messageHandler를 작동시켜
primary 내부의 변수의 값을 변화시킵니다.

실무에서는 pm2나 cluster 라이브러리를 사용하는게 낫습니다만

작게 작게 사용하려면 이 방법도 그냥 나쁘지 않아보입니다.

profile
이 블로그의 글은 제 생각을 정리한 글과 인터넷 어딘가에서 배운 것을 정리한 글입니다. 출처는 되도록 남기도록 하겠습니다. 수정 및 건의 오류 등이 있으면 언제든지 댓글 부탁드립니다.

0개의 댓글