2022. 5. 3. 19:49ㆍ책/Node.js 교과서
4. cluster
싱글 프로세스로 동작하는 노드가 CPU 코어를 모두 사용할 수 있게 해주는 모듈. 포트를 공유하는 노드 프로세스를 여러 개 둘 수 있어서 요청이 많이 들어와도 병렬로 실행된 서버의 개수만큼 요청이 분산되게 할 수 있다.
예를 들어 코어가 4개라고 치자. 노드는 보통 코어 하나만 활용하지만 cluster 모듈을 설정하면 코어 하나당 노드 프로세스 하나가 돌아가게끔 할 수 있다. 즉 같은 역할을 하는 서버를 4개 만큼 독립되게 열어두는 것. 성능이 꼭 4배가 되는건 아니더라도 코어를 하나만 쓸 때와 비교하면 성능이 개선된다. 물론 메모리를 공유하지 못하는 단점도 존재.
1) 클러스터링 해보기
const cluster = require('cluster');
const http = require('http');
// 지금 쓰고있는 노트북의 코어는 4개
const numCPUs = require('os').cpus().length;
if (cluster.isMaster) {
console.log(`마스터 프로세스 아이디: ${process.pid}`);
for (let i=0; i < numCPUs; i +=1 ) {
cluster.fork(); // 4개의 독립된 워커프로세스 생성
}
// 만약 워커프로세스가 종료되면('exit') 동작할 이벤트리스너
// process.pid - 프로세스 식별자(Process identifier)
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>');
// 요청이 오면 강제로 1초 뒤에 종료되도록 만들었다.
// 워커프로세스가 종료되면 마스터 프로세스의
// cluster.on('exit', listener)가 실행될 것이다.
setTimeout(() => {
process.exit(1);
}, 1000);
})
.listen(8086)
console.log(`${process.pid}번 워커 실행`);
}
콘솔
마스터 프로세스 아이디: 10156
21896번 워커 실행
12252번 워커 실행
16856번 워커 실행
13984번 워커 실행
13984번 워커가 종료되었음 <-- localhost/8086접속 후 1초 뒤...
code 1 signal null
16856번 워커가 종료되었음 <-- localhost/8086접속 후 1초 뒤...
code 1 signal null
12252번 워커가 종료되었음 <-- localhost/8086접속 후 1초 뒤...
code 1 signal null
21896번 워커가 종료되었음 <-- localhost/8086접속 후 1초 뒤...
code 1 signal null 여기까지 요청을 보내고나면 더이상 구동중인 서버가 없어서
localhost/8086으로 접속이 불가능해진다
2) 클러스터링 응용
위에서 4개의 워커 프로세스로 서버를 구동시켰다. 그리고 강제로 종료시키긴 했지만 4번까진 localhost/8086으로 서버 요청을 보낼 수 있었다. 이를 달리 말하면 만약 오류가 발생해서 서버가 강제종료 되더라도 4번 까지는 서버가 정상 작동할 수 있다는 뜻이다.
이 점에 착안해서 만약 워커 프로세스가 하나 종료되면 추가로 하나의 워커 프로세스가 구동되도록 코드를 작성할 수 있다. 물론 이런 식으로 에러 처리를 하는 방식은 좋지 않으나 예기치 못한 에러로 인해 서버가 완전히 죽어버리는 현상은 방지할 수 있어 의의가 있다.
if (cluster.isMaster) {
...
// 워커 프로세스가 종료된게 인지되면
// 워커 프로세스를 하나 추가로 열어준다
cluster.on('exit', (worker, code, signal) => {
cluster.fork();
})
...
클러스터링을 구현할 땐 직접 cluster 모듈을 사용해도 되지만, 실무에선 pm2 등의 모듈로 대체하곤 한다. 이는 15장에서 자세히 알아보기로 하자.
나아가 지금까지 노드의 http 모듈을 사용해 서버를 만들었지만 이 모듈만으로는 코드가 지저분해지고, 쿠키나 세션을 추가하면 더 길고 복잡해진다. 따라서 6장에서 Express 프레임워크를 통해 서버를 만들어보기로 하자.
※ 참고자료
• http 모듈 소개: https://nodejs.org/dist/latest-v16.x/docs/api/http.html
• 쿠키 설명: https://developer.mozilla.org/ko/docs/Web/HTTP/Cookies
• 세션 설명: https://developer.mozilla.org/ko/docs/Web/HTTP/Session
• https 모듈 소개: https://nodejs.org/dist/latest-v16.x/docs/api/https.html
• http2 모듈 소개: https://nodejs.org/dist/latest-v16.x/docs/api/http2.html
• cluster 모듈 소개: https://nodejs.org/dist/latest-v16.x/docs/api/cluster.html
'책 > Node.js 교과서' 카테고리의 다른 글
[6장] Express (0) | 2022.05.05 |
---|---|
[5장] npm 패키지 매니저 (0) | 2022.05.04 |
[4장] 서버 만들기(쿠키와 세션) (0) | 2022.05.03 |
[4장] 서버 만들기 (REST & Routing) (0) | 2022.05.03 |
[4장] 서버 만들기 (http모듈) (0) | 2022.05.01 |