Appearance
PM2 Safe Restart Configuration
글 작성 사유
- pm2 process를 재시작 할때, 모든 프로세스를 죽여버리면 프로세스가 다시 시작되기까지 서버 사용 불가.
- 검색 결과 노드 앱이 실행 되었다는 신호를 pm2와 주고받아서 pm2 process를 재시작 할때 순차적으로 프로세스들을 재시작 하게 할 수 있는 기능 발견.
pm2 wait_ready option
- 위 옵션은 기본값이 false로, 미설정 시 node server의 상황을 pm2가 몰라서 pm2 restart 시 모든 프로세스를 한번에 재시작을 해버림.
- 서비스가 중단이 되면 안되기 때문에 wait_ready option을 true로 설정 후 node server가 실행 됬을 때 pm2에게 서버가 살았다는 신호를 전송. pm2는 서버가 살았다는 신호를 받으면 다음 프로세스 진행.
ecosystem.config.js 수정
javascript
//ecosystem.config.js
module.exports = {
apps: [
{
name: 'app',
script: 'server.js',
instances: 4,
exec_mode: 'cluster', // 실행 모드. cluster로 명시하지 않으면 기본 fork 모드가 된다.
wait_ready: true, // Node.js 앱으로부터 앱이 실행되었다는 신호를 직접 받겠다는 의미
listen_timeout: 50000, // 앱 실행 신호까지 기다릴 최대 시간. ms 단위.
kill_timeout: 5000, // 새로운 프로세스 실행이 완료된 후 예전 프로세스를 교체하기까지 기다릴 시간
max_memory_restart: '500M', //프로세스 메모리 사용량이 증가했을 경우 재시작 하는 옵션
env: {
NODE_ENV: 'development',
},
env_production: {
NODE_ENV: 'production',
PORT: '8081',
},
},
],
};
app.ts 수정
- app 실행 상태 전송
javascript
const server = express();
const listeningServer = server.listen(port, (err) => {
console.log(`> Ready onhttp://localhost:${port}`);
// PM2가 스크립트를 실행하지 않았다면 process.send 메소드가 undefined일 수 있다.
if (process.send) {
// PM2에게 앱 구동이 완료되었음을 전달한다
process.send('ready');
}
});
- 서버가 시작되었으니 다른 프로세스를 재시작해도 된다는 신호 전송
javascript
let isAppGoingToBeClosed = false; // HTTP 연결을 종료시킬 미들웨어에서 사용할 변수
process.on('SIGINT', function () {
// SIGINT 신호가 수신되었을 때 console.log('> received SIGNIT signal')
isAppGoingToBeClosed = true;
// pm2 재시작 신호가 들어오면 서버를 종료시킨다.
// listeningServer: server.listen 메소드가 리턴하는 서버 인스턴스를 할당한 변수
listeningServer.close(function (err) {
console.log('server closed');
process.exit(err ? 1 : 0);
});
});
- 서버가 죽었으니 다른 프로세스로 요청을 넘기기 위한 클라이언트와 커넥션 종료
javascript
server.use(function (req, res, next) {
// 프로세스 종료 예정이라면 연결을 종료한다
if (isAppGoingToBeClosed) {
res.set('Connection', 'close');
}
next();
});