PM2

윤성준·2023년 10월 31일
0

Web Story

목록 보기
5/5

PM2란?

Node.js는 기본적으로 싱글 스레드로 돌아간다. 노드는 싱글 스레드이기 때문에 모든 코어를 사용하지 못해 최대 성능을 내지 못하게 된다.

Node.js 로 프로젝트를 마친 뒤 서비스로 운영하려고 할 때 데몬 프로세스로 서버를 띄우게 되는데 이 과정에서 nohup, forever, pm2 등 여러 패키지의 도움을 받을 수 있다.

이 중에서 지속적인 업데이트로 점유율이 높은 pm2를 알아보자.

PM2는 프로세스 관리자(process manager) 로 Node.js로 만들어진 프로그램의 프로세스를 편리하게 관리할 수 있도록 도와준다.

  • Node.js 기반 프로세스 관리
  • 무중단 서비스
  • 싱글 스레드 기반의 Node.js를 멀티 스레딩 혹은 하이퍼 스레딩으로 사용하기
  • 프로세스 모니터링 도구

단점도 존재 : 멀티 스레딩이 아니므로 서버의 메모라 같은 자원을 공유하지는 못한다.

PM2 모듈 사용법

pm2 설치

$ npm install -g pm2 # pm2 설치

$ pm2 -version # pm2 버젼 확인

$ pm2 update # pm2 업데이트

pm2 실행

$ pm2 start <파일명>

pm2 실행 옵션(클러스터)

$ pm2 start -- 실행 옵션
  • --watch : PM2가 실행된 프로젝트의 변경사항을 감지하여 서버를 자동 재시작(reload)
    nodemon과 유사하다, 주로 개발단계에서 즉시 반영되므로 매우 편리하게 사용 할 수 있다.
    만일 watch옵션시에 특정 폴더 경로는 무시해야할 때 --watch --ignore-watch="[dir]/*"

  • -i max(코어개수) : Node.js의 싱글 스레드를 보완하기 위한 클러스터(Cluster) 모드
    -i 뒤에 코어의 개수를 입력하거나 max를 쓰면 최대 코어 개수로 클러스터링(Clustering) 된다.

  • --name : 앱 이름 지정

  • --max-memory-restart <200MB> : 앱이 리로드 될때 최대의 메모리 지정

  • --log <log_path> : 로그 파일 경로 지정

  • -- arg1 arg2 arg3 : 스크립트에 추가 인수 전달

  • --restart-delay : 재시작할때의 딜레이 지정

  • --time : 로그 남길때 프리픽스로 시간 지정

  • --no-autorestart : 재시작 불가하도록 설정

  • --cron <cron_pattern> : 주기적으로 강제 재시작이 필요할때 설정 (cron)

pm2 프로페스 증설(scale)

만약 프로세스 개수를 늘리거나(scale up) 줄여야(scale down) 한다면 pm2 scale 명령어를 사용해서 실시간으로 프로세스 수를 증가시키거나 감소시킬 수 있다.

$ pm2 scale app +2 # app 프로세스 개수 +2

$ pm2 scale aap 4 # app 프로세스 개수 4개로 고정

pm2 상태 확인(ls l status)

status와 ls를 이용해 현재 프로세스 리스트를 띄울 수 있다. (둘이 같은 명령)

프로세스 아이디(pid), CPU와 메모리 사용량(mem) 등이 보여 편리하다.

uptime과 status 사이에 ↺ 재시작된 횟수가 나오는데, 횟수가 많으면 아니라면 서버가 자꾸 에러나서 재부팅된 것이니 이 경우 서버 개발자는 프로세스가 왜 재시작되었는지 로그를 통해 확인해봐야 한다.

status 도 서버가 자꾸 에러가 나면 online이 아닌 경우도 있다.

$ pm2 status
$ pm2 ls
$ pm2 l

pm2 프로세스 중지(stop)

클러스터링 된 여러개의 프로세스중에 특정 프로세스를 골라 중지 할 수 있다.

중지된 프로세스는 아직 pm2가 관리하고 있는 상태이다.

$ pm2 stop <app_name | namespace | id | 'all' | json_conf>

$ pm2 stop 2 # id 2번 프로세스를 멈춤

$ pm2 stop app # 이름을 줘도 됨. (전체 프로세스 멈춤)

pm2 프로세스 재시작(restart)

$ pm2 restart <app_name | namespace | id | 'all' | json_conf>

$ pm2 restart 2 # 위에서 중지한 2번 프로세스를 재시작
  
$ pm2 restart app.js # 파일명을 써서 전체 서비스를 재시작

pm2 프로세스 리로드 (reload)

$ pm2 reload <app_name | namespace | id | 'all' | json_conf>

$ pm2 reload app
$ pm2 reload all

pm2 reload vs restart 차이점

pm2 restart는 모든 프로세스를 죽인다음 다시 시작하는 방법이기 때문에 아주 잠깐동안 서비스를 이용하지 못하는 상황이 생긴다.

pm2 reload는 하나씩 프로세스를 죽여서, 최소한 1개 이상의 프로세스를 유지하며 하나씩 재시작 하는 방식. 서비스를 이용 못하는 상황을 미연에 방지한다.

0-second-downtime 이라고 불리운다.
이러한 방식 때문에 reload는 restart보다 재실행 속도가 느리다는 단점이 있다.

pm2 프로세스 삭제(delete l kill)

돌아가고 있는 특정 프로세스를 죽이고 싶다면 delete 명령어에 프로세스 id를 찍어주면 된다.

$ pm2 delete <app_name | namespace | id | 'all' | json_conf>

$ pm2 delete 2 # 특정 프로세스 삭제

$ pm2 delete app # 프로세스 name이 app인 거 모두 삭제

kill 명령어로 모든 프로세스를 한번에 죽일 수 있다.

pm2 kill # 프로세스 전체 삭제

pm2 로그 보기(log)

기본 로그파일 위치: /root/.pm2/pm2.log

만일 에러 로그만 보고싶다면 뒤에 -err을 붙이면 된다.
출력 줄 수를 변경하고 싶다면 --lines 숫자 옵션 사용한다.

$ pm2 log # 전체 프로세스 로그 보기

$ pm2 log [process name | process id] # 특정 프로세스 로그 보기

$ pm2 log --lines 200 # 200줄 까지만 보기

$ pm2 log --err 200 # 에러 로그만 보기

pm2 로그 관리(logrotate)

pm2를 실행할때마다 로그 경로에 저장되는 로그들은 직접 삭제해주지 않는한 계속 쌓이게 된다.

이렇게 계속 쌓이게 된다면 서버 용량 부족으로 이어질 수도 있는데, 이를 해결하기 위해서 로그 파일을 관리해주는 pm2-logrotate라는 plugin을 사용한다.

$ pm2 install pm2-logrotate # npm으로 설치하는 것이 아닌 pm2로 설치

$ pm2 set pm2-logrotate:<option> <value> # 옵션 설정은 다음과 같이 설정
$ pm2 set pm2-logrotate:max_size 1K
$ pm2 set pm2-logrotate:retain 10

options

  • max_size: 로그 파일 사이즈 제한 크기 (기본값은 10M)
  • retain: 로그 파일을 최대 몇개까지 가지고 있을 것인지 설정 (기본값은 30개)
  • compress: 로그 파일을 gzip으로 압축할 것인지 여부 (기본값은 false)
  • dateFormat: 로그 파일 날짜 폼새 (기본값은 YYYY-MM-DD_HH-mm-ss)
  • workerInterval: 로그 파일 사이즈를 확인하는 1초마다의 회수 (기본값 초당 30회)
  • rotateInterval: cron job (기본값은 '0 0 * * *')

pm2 프로세스 정보(show l describe)

$ pm2 show <id> | <name>
$ pm2 describe <id> | <name>

pm2 모니터링(monit)

pm2로 실행한 서버들의 상황을 한눈에 확인 할 수 있는 monit 명령어는 아래 할목을 실시간 상태를 확인할 수 있는 모니터링 창을 띄워준다

$ pm2 monit

pm2 설정 파일로 관리하기

pm2 설정 파일 만들기(ecosystem.config.js)

npm을 관리하기 위해 package.json 설정 파일을 만들었듯이, pm2를 보다 수월하게 관리하기 위해 ecosystem.config.js 라는 파일을 만들어 설정할 수 있다.

$ pm2 ecosystem # ecysystem.config.js 파일이 생성
module.exports = {

 /* apps 항목은 우리가 pm2에 사용할 옵션을 기재 */
 apps: [
    {
       name: 'projectName', // app이름
       script: './index.js', // 실행할 스크립트 파일
       instances: 2, // cpu 코어수 만큼 프로세스 생성 (instance 항목값을 ‘0’으로 설정하면 CPU 코어 수 만큼 프로세스를 생성)
       exec_mode: 'cluster', // 클러스터 모드
       max_memory_restart: '300M', // 프로세스의 메모리가 300MB에 도달하면 reload 실행
       
       watch: ['bin', 'routes'], //bin폴더, routes폴더를 감시해서 변경사항 실행
       ignore_watch: ['node_modules'], // 반대로 해당폴더의 파일변경은 무시
       
       env: {
          // 환경변수 지정
          Server_PORT: 4000,
          NODE_ENV: 'development',
          Redis_HOST: 'localhost',
          Redis_PORT: 6379,
       },
       
       output: '~/logs/pm2/console.log', // 로그 출력 경로 재설정
       error: '~/logs/pm2/onsoleError.log', // 에러 로그 출력 경로 재설정
    },
 ],

 /* deploy는 원격 서버와 git을 연동해서 배포하는 방식 */
 deploy: {
    production: {
       user: 'SSH_USERNAME',
       host: 'SSH_HOSTMACHINE',
       ref: 'origin/master',
       repo: 'GIT_REPOSITORY',
       path: 'DESTINATION_PATH',
       'pre-deploy-local': '',
       'post-deploy': 'npm install && pm2 reload ecosystem.config.js --env production',
       'pre-setup': '',
    },
 },
};

모든 설정을 맞추고 나면 설정 파일을 실행해준다.

$ pm2 start ecosystem.config.js

pm2 개발/배포 환경 실행 분리

module.exports = {
 apps: [
    {
       /* 개발 환경용 서버 */
       name: 'projectName-dev',
       script: './app.js',
       instances: 1, // 단일 쓰레드
       autorestart: false,
       watch: false,
       env: {
          Server_PORT: 4000,
          NODE_ENV: 'development',
       },
    },
    {
       /* 배포 환경용 서버 */
       name: 'projectName-product',
       script: './app.js',
       instances: -1, // 클러스터 모드
       autorestart: false,
       watch: false,
       env: {
          Server_PORT: 1234,
          NODE_ENV: 'production',
       },
    },
 ],
};

그리고 package.json 파일에서 scripts 영역에 다음과 같이 명령 구문을 넣는다

"scripts": {
  "dev": "pm2 start ecosystem.config.js --only projectName-dev --env development",
  "start": "pm2 start ecosystem.config.js --only projectName-product --env production",
  "del": "pm2 del all"
},

위 명령어에서 중요한 옵션은 --only와 --env 이다.

  • --only 옵션은 ecosystem.config.js 파일에서 name 값을 지정해서 실행시켜주는 옵션이다.
  • --env 옵션은 실행되는 항목에 env 설정들을 실행시켜주는 옵션이다.
    따라서 다음과 같이 개발 모드와 배포 모드에서 각각 따로 실행되게 구성할 수 있다.
$ npm start # 배포환경으로 pm2 실행

$ npm run dev # 개발환경으로 pm2 실행
profile
반갑습니다

0개의 댓글