cpu 활용도를 높이기 위해 cluster를 적용시켜보겠습니다. 클러스터 적용을 위해 bin/www
파일을 수정해야합니다. 코드부터 봅시다.
const app = require('../app');
const debug = require('debug')('myapp:server');
const http = require('http');
const cluster = require('cluster');
const numWorker = require('os').cpus().length/2;
const isPrimary = cluster.isPrimary || cluster.isMaster;
const port = normalizePort(process.env.PORT || '3000');
if(isPrimary) {
for(let i=0;i<numWorker;i++) {
cluster.fork();
}
// worker가 죽으면 새로 만듦
cluster.on('exit',(worker, code, signal)=> {
console.log(`worker ${worker.process.pid} died`);
cluster.fork();
})
}
else {
app.set('port', port);
const server = http.createServer(app);
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);
function onError(error) {
if (error.syscall !== 'listen') {
throw error;
}
const bind = typeof port === 'string'
? 'Pipe ' + port
: 'Port ' + port;
// handle specific listen errors with friendly messages
switch (error.code) {
case 'EACCES':
console.error(bind + ' requires elevated privileges');
process.exit(1);
break;
case 'EADDRINUSE':
console.error(bind + ' is already in use');
process.exit(1);
break;
default:
throw error;
}
}
function onListening() {
const addr = server.address();
const bind = typeof addr === 'string'
? 'pipe ' + addr
: 'port ' + addr.port;
debug('Listening on ' + bind);
}
}
...
간단합니다. 그냥 server.listen 부분을 cluster로 감싼 것 뿐이에요. 뭔가 눈여겨볼 부분이 있다면, nodejs 최신 버전에선 cluster의 isMaster가 isPrimary로 바뀌었기 때문에 버전구분 없이 사용할 수 있게 isPrimary 상수에 cluster.isPrimary와 cluster.isMaster 중 존재하는 값으로 사용합니다.
추후에 2개의 container로 서버를 돌릴 예정이기 때문에 worker의 개수는 cpu 총 개수의 절반만큼 만들어줍니다.
primary 프로세스인 경우 worker를 생성합니다. 그리고 cluster가 죽으면 (exit이 발생하면) 새 cluster를 fork해줍니다. 일정 클러스터수를 유지해주겠죠.
이게 답니다. 다음은 docker-compose와 nginx를 설정해 라즈베리파이에 탑재시켜봅시다.