출처 : Elastic 가이드북
cluster 모듈
은 싱글 스레드인 노드가 CPU 코어
를 모두 사용할 수 있게 해주는 모듈이다. 포트를 공유하는 노드 프로세스를 여러개 둘수도 있어 요청이 많이 들어왔을 경우 요청을 분산되게 할 수 있다.
예를들면, 코어가 8개인 서버가 있을때 노드는 보통 코어를 하나만 사용하는데, cluster 모듈
을 설정하면 코어 하나당 노드 프로세스 하나가 돌아가게 할 수 있다. 성능이 개선되기는 하지만, 세션을 공유하지 못한다는 단점이 있다.(Redis 등의 서버 도입으로 해결 가능)
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}번 워커가 종료되었습니다.`);
});
} else {
// 워커들이 포트에서 대기
http.createServer((req, res) => {
res.write('<h1>Hello Node!</h1>');
res.end('<p>Hello Cluster!</p>');
}).listen(8085);
console.log(`${process.pid}번 워커 실행`);
}
다음은 클러스터링
을 진행한 코드이다.
클러스터
에는 마스터 프로세스
와 워커 프로세스
가 있다. 마스터 프로세스
는 CPU 개수만큼 워커 프로세스
를 만들고, 8085번 포트에서 대기한다. 요청이 들어오면 만들어진 워커 프로세스
에 요청을 분배한다.
여기서 워커 프로세스
는 실질적인 일을 하는 프로세스이다.
컴퓨터 CPU 개수가 8개인경우 워커가 8개 생성되는데, 실제로 8개가 생성되는지 확인해보쟈
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}번 워커가 종료되었습니다.`);
});
} else {
// 워커들이 포트에서 대기
http.createServer((req, res) => {
res.write('<h1>Hello Node!</h1>');
res.end('<p>Hello Cluster!</p>');
setTimeout(() => {
process.exit(1);
}, 1000);
}).listen(8085);
console.log(`${process.pid}번 워커 실행`);
}
요청이 들어올 때마다 1초 후에 서버가 종료되는 코드다. process.pid
는 매 실행시마다 달라진다.
13468번 워커 실행
9800번 워커 실행
11996번 워커 실행
7768번 워커 실행
8304번 워커 실행
14884번 워커 실행
6972번 워커 실행
2624번 워커 실행
17360번 워커 실행
3124번 워커 실행
18236번 워커 실행
3564번 워커 실행
8384번 워커 실행
14996번 워커 실행
10152번 워커 실행
13020번 워커 실행
나는 CPU가 16개인가부다.
이제 8085 포트에 접속하면 1초 후 콘솔에 워커가 종료되었다는 메세지가 뜬다. 새로 고침할때마다 워커가 하나씩 종료된다~!
즉, 16번까지는 오류가 발생해도 서버가 정상 작동될 수 있다. 또한 종료된 워커를 다시 켜면 오류가 발생해도 계속 버틸 수 있다.
또한, 워커가 종료되었을때마다 새로운 워커를 재 생산할수도 있다. 워커가 종료되었다는 콘솔 밑에
cluster.fork();
해당 코드만 입력해주면,
13020번 워커가 종료되었습니다.
1284번 워커 실행
1284번 워커가 종료되었습니다.
11480번 워커 실행
11480번 워커가 종료되었습니다.
11616번 워커 실행
11616번 워커가 종료되었습니다.
12900번 워커 실행
12900번 워커가 종료되었습니다.
16408번 워커 실행
16408번 워커가 종료되었습니다.
1976번 워커 실행
10152번 워커가 종료되었습니다.
7532번 워커 실행
종료될때마다 워커를 하나 더 생성할 수 있다.
하지만, 이런 방식으로 오류를 막기만 한다면 오류 자체의 원인을 파악할 수 없게 된다. 물론 예기치 못한 에러로 인해 서버가 종료되는 현상을 방지하기 위해서는 클러스터링
을 적용하는 것이 좋다!!!