Node Schedule & PM2
“매일 정기적으로 같은 시간에 같은 일을 실행시킨다.”
개요
- “node-schedule”가 무엇인지
- Jobs and Scheduling
- 시간 설정 방식
- 서버 재실행에 자유로운 scheduling 구현
- 멀티프로세스에서 중복되지않는 scheduling 구현
“node-schedule”가 무엇인지
Node Schedule 은 cron과 비슷하기도 하고 cron과 비슷하지만은 않은 스케줄러입니다. node-schedule은 “특정 작업”을 “특정 반복 조건”에 맞게 스케줄링(예약)할 수 있게 해줍니다.
node-schedule을 이용하기전에 확인하고 넘어갑시다.
상황에 따른 대체제 toad-scheduler/ cron
- 특정한 시간에 작동하도록 예약하는 것이 아니라 특정 간격 마다 작동시키는 것을 원한다면(예를 들어, A함수를 5분마다 작동킨다.), toad-scheduler를 이용하는 게 더 좋을 것입니다.
- Node 서버가 꺼져있는 상태에서는 작동하지 않습니다. Node 서버가 꺼져있을 때까지 작동하길 원한다면 OS에서 작동할 수 있는 cron을 이용하시기 바랍니다.
Jobs and Scheduling
node-schedule
에서 예약하려는 모든 일들을 "Job" 객체라고 합니다. 직접 job들을 만들 수 있고, schedule()
함수를 이용하여 시간을 설정합니다.
다른 여러 노드 객체들처럼 Job 객체 또한 EventEmitter입니다. 그러므로 이벤트를 발생시켜 일을 처리하게 됩니다. 자주쓸 이벤트는 아래 4가지입니다.
run
: 각각의 job이 실행된 후에 발생하는 이벤트.scheduled
: 각각의 job이 예약되었을 때의 이벤트.canceled
: 각각의 job이 취소되었을 때의 이벤트.error
: 각각의 job에 에러가 발생했을 때의 이벤트.
시간 설정 방식
Cron 스타일식 시간 설정
여섯개의 시간 설정 항목이 있고 띄어쓰기로 항목이 분리됩니다. *(별표) 표시는 all을 의미하므로 무작정 별표를 넣으시면 안되니 주의하세요.
example)
const schedule = require('node-schedule');const job = schedule.scheduleJob('42 * * * *', function(){
console.log('The answer to life, the universe, and everything!');
});// 매시간 42분에 예약하기. (eg, 19:42, 20:42)
const job = schedule.scheduleJob('0 17 ? * 0,4-6', function(){
console.log('Today is recognized by Rebecca Black!');
});
Date 스타일식 시간 설정
매우 특정한 시간에 작동시키길 원할 때 이용합니다.
const schedule = require('node-schedule');
const date = new Date(2012, 11, 21, 5, 30, 0);const job = schedule.scheduleJob(date, function(){
console.log('The world is going to end today.');
});
재귀식 규칙 시간 설정 (Recurrence Rule)
반복적으로 규칙에 맞게 job을 실행시켜야 한다면 RecurrenceRule()
을 이용하면 됩니다.
const schedule = require('node-schedule');const rule = new schedule.RecurrenceRule();
rule.minute = 42;const job = schedule.scheduleJob(rule, function(){
console.log('The answer to life, the universe, and everything!');
});
타임존 또한 설정가능합니다.
rule.tz = 'ETC/UTC'
rule에 설정할 수 있는 값들입니다.
- second (0–59)
- minute (0–59)
- hour (0–23)
- date (1–31)
- month (0–11)
- year
- dayOfWeek (0–6) Starting with Sunday
- tz
서버 재실행에 자유로운 scheduling 구현:
“Node 서버가 재실행되더라도 예약된 작업들이 살아있어야 한다.”
기본적으로 node-schedule
은 서버가 꺼지면 사라집니다. 이를 해결할 방법은 여러가지가 있습니다.
- cron: OS단에서 예약된 작업을 실행하기때문에 node 서버가 재부팅된 상태여도 예약된 작업들이 살아있습니다.
- agenda.js: 작업들을 DB(mongoDB)에 저장하여서 불러오기 때문에 서버가 꺼져도 예약된 작업들이 서버의 살아있음 유뮤 상관없이 작동합니다.
- node-schedule: 서버를 실행시키는 코드에 node-schedule 예약 코드를 넣어둡니다. db를 연결하거나, 서버에 필요한 것들을 실행시키는 코드(/src/index.js 파일)에 스케줄링코드까지 집어넣습니다. 그러면 매번 서버가 재실행될때마다 작업이 예약되므로 계속 유지할 수 있습니다.
but 서버를 한개의 instance로만 실행시킬수는 없는 노릇입니다. 이 방식대로 하면 실행되는 모든 node instance에서 실행되므로 job이 중복되게 실행되는 문제가 발생합니다. - pm2: pm2를 이용한다면 서버에 문제가 생겨 멈추어버렸을 때 알아서 다시 시작하게 됩니다. 그리고 특정 프로세스에만 scheduling을 설정할 수 있습니다.
멀티프로세스에서 중복되지않는 scheduling 구현:
“하나의 프로세서에서만 scheduling이 실행되어야만 한다.”
서버로 들어오는 요청을 하나의 프로세스에서 모두 처리하기는 힘듭니다. 그래서 cpu만큼 프로세스를 만들어 멀티 프로세스로 요청을 처리하게 됩니다. 보통 node로 서버를 구축할 때는 pm2
를 이용하여 여러개의 프로세스를 관리하게 됩니다.
pm2 & node-schedule
pm2에서는 process마다 번호를 제공해줍니다. 그 번호를 이용하여 특정 process에게만 scheduling을 설정할수 있고, 하나의 프로세스에서만 예약된 작업이 실행되게 할 수 있습니다. node-schedule을 이용하며 아무런 설정도 하지 않는다면 여러 개의 프로세스에서 job을 실행하여 예상하지 못한 일이 발생할 수 있습니다.
pm2 — NODE_APP_INSTANCE
https://pm2.keymetrics.io/docs/usage/environment/#node_app_instance-pm2-25-minimum
위 링크를 들어가보시면 pm2 document 자체적으로도 NODE_APP_INSTANCE
변수를 scheduling에 이용하라고 합니다. 다른 이름으로 사용하고 싶다면, pm2.config.js
에서 instance_var
를 설정하시면 됩니다.
module.exports = {
apps : [{
name: 'appName',
script: 'src/index.js',
instance_var: 'INSTANCE_ID', // 편한 이름으로 설정하면 됩니다.
instance: 0,
exec_mode: 'cluster',
min_uptime: 5000,
max_restarts: 5,
args: '',
env:{
NODE_ENV:'production'
}
}],
};
그리고 이 변수를 이용하여 하나의 프로세서에서만 스케줄을 설정하도록 하면 됩니다.
// index.js~~if (process.env.INSTANCE_ID == 0) {
// schedule your job here.
}
pm2에서 첫번째 프로세스는 0이므로 첫번째에서만 scheduling해두면 job이 중복되어 실행되지 않게 됩니다. 참고stackoverflow
마무리
scheduling하는 것은 그리 어렵지않기 때문에 아무 것이든 사용해도 큰 문제가 되지 않습니다. 편하신 걸 이용하시기 바랍니다.