Node.js 클러스터 모드
Node.js는 기본적으로 단일 스레드로 동작합니다. 멀티코어 CPU를 활용하려면 클러스터 모듈을 사용하여 여러 워커 프로세스를 생성해야 합니다.
네이티브 클러스터 모듈
const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;
if (cluster.isPrimary) {
console.log(`Primary ${process.pid} is running`);
console.log(`CPU cores: ${numCPUs}`);
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('exit', (worker, code, signal) => {
console.log(`Worker ${worker.process.pid} died (${signal || code})`);
console.log('Starting a new worker...');
cluster.fork();
});
for (const id in cluster.workers) {
cluster.workers[id].on('message', (msg) => {
console.log(`Message from worker ${id}: ${msg}`);
});
}
} else {
http.createServer((req, res) => {
res.writeHead(200);
res.end(`Worker ${process.pid} handled this request
`);
}).listen(3000);
console.log(`Worker ${process.pid} started`);
}
PM2 기본 사용법
# PM2 설치
npm install -g pm2
# 클러스터 모드로 실행
pm2 start app.js -i max --name my-app
# 주요 명령어
pm2 list # 프로세스 목록
pm2 monit # 실시간 모니터링
pm2 logs my-app # 로그 확인
pm2 restart my-app # 재시작
pm2 reload my-app # 무중단 리로드
pm2 stop my-app # 중지
pm2 delete my-app # 삭제
PM2 Ecosystem 설정 파일
// ecosystem.config.js
module.exports = {
apps: [{
name: 'my-app',
script: './dist/server.js',
instances: 'max',
exec_mode: 'cluster',
max_memory_restart: '1G',
env: {
NODE_ENV: 'development',
PORT: 3000
},
env_production: {
NODE_ENV: 'production',
PORT: 8080
},
log_file: '/var/log/pm2/combined.log',
error_file: '/var/log/pm2/error.log',
out_file: '/var/log/pm2/out.log',
log_date_format: 'YYYY-MM-DD HH:mm:ss Z',
merge_logs: true,
listen_timeout: 8000,
kill_timeout: 5000,
wait_ready: true,
watch: false,
max_restarts: 10,
restart_delay: 4000,
autorestart: true,
shutdown_with_message: true
}]
};
Graceful Shutdown 구현
const server = require('http').createServer(app);
server.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
if (process.send) {
process.send('ready');
}
});
process.on('SIGINT', gracefulShutdown);
process.on('SIGTERM', gracefulShutdown);
async function gracefulShutdown(signal) {
console.log(`${signal} received. Graceful shutdown...`);
server.close(async () => {
await database.disconnect();
await redis.quit();
console.log('Process terminated gracefully');
process.exit(0);
});
setTimeout(() => {
console.error('Forced shutdown after timeout');
process.exit(1);
}, 10000);
}
PM2 모니터링 및 배포
| 기능 | 명령어 | 설명 |
|---|---|---|
| 모니터링 | pm2 monit | CPU/메모리 실시간 모니터링 |
| 스타트업 | pm2 startup | 시스템 부팅 시 자동 실행 |
| 저장 | pm2 save | 현재 프로세스 목록 저장 |
| 배포 | pm2 deploy | 원격 서버 배포 자동화 |
| 키메트릭 | pm2 plus | 웹 기반 모니터링 대시보드 |
pm2 reload는 새 워커를 먼저 시작하고 이전 워커를 종료하므로 무중단 배포 가능max_memory_restart로 메모리 누수 시 자동 재시작pm2 startup으로 서버 재부팅 시에도 자동 복구- 프로덕션에서는 반드시 Graceful Shutdown을 구현하여 요청 손실 방지
댓글 0