본문 바로가기
웹 백엔드/NodeJS, PM2

pm2 : 1개의 cluster에서만 cronjob 수행하기 (instance_var 옵션)

by 번데기 개발자 2023. 7. 23.
반응형

개요

 

최근에 회사에서 nodeJS 통해 백엔드 개발을 하고 있습니다.

 

그러던중 특정 시간에 실행되는 CronJob 서비스를 구현해야할 일이 생겼습니다. echosystem.config.js 환경을 만들고 pm2를 통해 서비스를 구동시키고 있는데요, 로직을 다 만들고 나니 문제가 하나 발생하였습니다.

 

pm2를 통해 하나의 EC2 인스턴스의 core갯수에 맞게 cluster 들을 구성한것은 좋았지만, 각각의 cluster들에서 특정시간에 cron작업이 동시에 일어난다는 문제가 발생하였습니다. 사실 cronJob 작업은 모든 cluster에서 동작해야 하는 것이 아니라 특정 시간에 1개의 cluster에서 한번만 일어나면 되기 때문에 이러한 부분을 어떻게 해결해야 될지 고민하였습니다. 

 

이에 대해서 pm2 옵션을 통해 해결하였는데, 이에 대해서 공유드리도록 하겠습니다.

 

 

 

pm2의 instance_var 속성을 이용하여 특정 프로세스에서 cron 테스크 수행

 

instance_var 속성은 PM2 2.5 버전 이상 일 때 사용할 수 있는 속성입니다. instance_var 을 통해 프로세스별로 다른 번호를 부여해줄수 있기 때문에, 이를 통해서 특정 프로세스에서만 동작하는 작업을 수행할 수 있습니다. 

 

PM2 에 instance_var을 적용하는 방법은 아래와 같습니다.

module.exports = {
  apps : [
      {
        name: "myapp",
        script: "./app.js",
        watch: true,
        instance_var: 'INSTANCE_ID',
        env: {
            "PORT": 3000,
            "NODE_ENV": "development"
        }
      }
  ]
}

위와 같이 설정하면 Node.js 코드에서 process.env.INSTANCE_ID 라는 값으로 현재 프로세스의 번호를 확인할 수 있습니다.

 

 

@Cron('0 10 * * *', {
  timeZone: 'Asia/Seoul',
})
async myCronjob() {
  // pm2 instance_var 속성, pm2 cluster 넘버링을 위해 사용
  const instanceId: string | undefined = process.env.INSTANCE_ID;

  // 첫번째 instanceId 일 때만 cronjob을 통해 task 수행
  if (instanceId && parseInt(instanceId) === 0) {
    await this.doSomething();
  }
}

 

이후 코드상에서 위와 같이 적용하여 특정 프로세스에서만 Cron 서비스를 수행하는 코드를 작성하였습니다. 위는 nestJS에서 통해 크론 서비스를 수행하는 코드인데요, 매일 오전 10시에 CronJob 작업을 수행하는데 만약 instanceId가 존재하지 않거나 instancId가 0일 경우에는 특정 작업을 수행하지 않도록 선언하였습니다.

 

instance_var 속성의 한계점

 

instance_var 속성의 한계점은 하나의 PM2 프로세스의 cluster 들에게만 해당 속성을 적용할수 있다는 점입니다.

 

예를 들어 여러개의 서버에 배포된 EC2 인스턴스에 ELB(로드밸런서)를 적용한 상황이라고 가정한다면, 각각의 EC2 인스턴스의 첫번째 cluster에서는 Cronjob이 일어나게 되기때문에 인스턴스의 갯수만큼 특정 시간에 Cron 테스크가 동작하게 됩니다.

 

이를 해결하기 위한 방법은 PM2만으로는 부족하고, 따로 해당 작업을 위한 CronJob을 위한 별도의 서버를 구축하거나, Redis와 같은 분산환경에서 데이터를 쉽게 저장할수 있는 DB를 통해 분산 락(Distributed Lock)을 활용하거나 서버간의 동기화를 처리할수있는 다른 방법들을 고안해야 합니다.

 

 

 

 

마무리

 

오늘은 PM2 instance_var 라는 속성을 통해서 특정 클러스터에서만 동작하는 태스크를 만드는 방법에 대해서 알아보았습니다.

 

PM2의 옵션은 자세히 살펴볼수록 흥미로운 옵션들이 많이 있는것 같습니다.

 

NodeJS 기반 서버 개발자라면 해당 옵션들을 잘 숙지해두고 적절하게 사용하는것이 중요한 것 같습니다.

 

다음번에도 흥미로운 주제로 찾아오겠습니다. 

 

감사합니다.

 

 

 

 

 

 

 

 

 

 

반응형