PM2를 통한 서버 프로세스 관리 - ZZinBros/miniprojects-2019 GitHub Wiki

소개

PM2는 서버 프로세스를 관리하는 프로그램입니다. 서버 프로세스가 바뀌면 자동으로 다시 로드해주고, 여러 개의 서버 프로세스를 관리하는 기능이 있습니다. Jenkins에서는 순수하게 빌드만 돌리고, PM2에서 새로 빌드된 프로그램을 자동으로 띄워주는 방식으로 사용할 수 있습니다.

PM2 홈페이지: http://pm2.keymetrics.io/

설치

PM2는 Node.js 기반으로 작동하는 프로그램입니다. 따라서, 시스템 전역으로 Node.js가 설치되어 있어야 합니다.

sudo apt-get update
sudo apt-get install nodejs

일단 Node.js가 시스템 전역으로 설치되어 있다면, 다음 명령으로 PM2를 시스템 전역 명령으로 설치할 수 있습니다.

npm install pm2 --global

설정 파일 준비

PM2로 Java 서버 프로그램을 실행시키기 위해서는 먼저 앱이름.config.js 또는 이에 상응하는 JSON 파일을 준비해야 합니다. 만약 js 파일을 사용한다면, 확장자 앞에 반드시 .config라고 붙여줘야 합니다.

현재 저희 서버에서 돌리고 있는 zzinbros.config.js 파일의 내용은 다음과 같습니다.

module.exports = {
  apps: [{
    name: "zzinbros",
    cwd: ".",
    interpreter: "/usr/bin/java",
    interpreter_args: "-jar",
    script: "/var/lib/jenkins/workspace/demo-test/out/zzinbros-0.0.1-SNAPSHOT.jar",
    args: [],
    env: {
      PORT: 8080,
      SPRING_PROFILES_ACTIVE: "deploy"
    },
    watch: ["/var/lib/jenkins/workspace/demo-test/out/"],
    restart_delay: 10000,
    max_restarts: 10,
    kill_retry_time: 10000,
    max_memory_restart: "2G"
  }]
};

여기서 사용한 각 항목들의 의미는 대략 다음과 같습니다.

  • name: PM2에서 관리용으로 사용할 이름입니다. 이를 사용하여 서버를 강제 종료하거나 할 때 PID를 일일히 찾을 필요 없이 이름으로 종료하거나 재시작할 수 있습니다.
  • cwd: 서버 프로그램이 실행될 위치입니다. 이 디렉터리에 로그 파일 등이 생성될 것입니다.
  • interpreter: Java 파일을 실행시키기 위한 해석 프로그램(여기서는 JVM)의 절대 경로입니다.
  • interpreter_args: 여기서는 JAR 파일을 실행시키기 위해 사용했습니다.
  • script: 실제로 실행해야 할 서버 프로그램의 위치입니다.
  • args: 서버 프로그램에 뭔가 실행 인자를 넘겨줘야 할 때 사용합니다.
  • env: 서버 프로그램을 실행할 때 사용할 환경 변수입니다.
  • SPRING_PROFILES_ACTIVE: 이건 Spring 프레임워크에서 사용하는 환경 변수입니다. 어느 프로파일을 사용할지 결정합니다. 현재 배포 환경에서는 deploy를 사용하기로 하였습니다.
  • watch: 파일 변경을 감시할 디렉터리의 목록입니다. 프로젝트의 최상위 디렉터리를 지정하면 하위 디렉터리의 변경 사항까지 모두 감시할 수 있습니다. 만약 Jenkins 작업 디렉터리의 build/libs/ 디렉터리만 감시하도록 할 경우, clean build로 인해 감시중이던 디렉터리가 삭제되므로 이후 변경 사항을 감지하지 못하는 경우가 있습니다.
  • restart_delay: 재시작할 때 둘 시간 간격입니다. 단위는 밀리초(ms)입니다.
  • max_restarts: 만약 빌드된 서버 프로그램에 심각한 문제가 있다면 아무리 다시 실행시켜도 계속해서 죽을 것입니다. 그럴 경우를 대비하여, 서버 프로그램이 연속으로 몇 번 이상 죽을 경우 더 이상 재시작을 하지 않는 기능이 있습니다. 이것은 그 횟수 한도입니다.
  • max_memery_restart: 실행시킨 서버 프로그램이 지정된 메모리 한도를 초과하면 재시작하게 하는 옵션입니다.

사용법

설정 파일이 준비된 경우, PM2의 사용법은 아주 간단합니다. 설정 파일을 통해 서버를 시작하고 싶다면 다음 명령어를 사용하면 됩니다.

pm2 start zzinbros.config.js

만약 지금 서버가 켜져 있는지 확실하지 않다면 다음과 같이 하면 됩니다.

pm2 startOrRestart zzinbros.config.js

아니면, 이미 이름이 등록된 경우라면 그냥 이름만 써줘도 무방합니다.

pm2 startOrRestart zzinbros

현재 실행중인 서버 프로세스를 확인하려면 다음과 같이 하면 됩니다.

pm2 list

서버에서 출력되는 화면 등 여러 정보를 확인하는 기능도 있습니다.

pm2 monit

이 화면은 상하좌우 화살표 키를 사용하여 조작할 수 있습니다. 이 화면에서 나가려면 q 키를 누르면 됩니다.

로그를 확인하고 싶으면 다음 명령어를 사용합니다.

pm2 logs

서버 프로세스를 멈추려면 다음과 같이 합니다. 여기서 zzinbros는 설정 파일의 name에 지정된 이름입니다.

pm2 stop zzinbros

PM2의 관리 서비스 목록에서 앱을 지우려면 다음과 같이 합니다.

pm2 delete zzinbros

서비스 등록

서버가 재부팅될 때마다 PM2를 재시작하려면 다음 명령을 실행한 다음, 화면의 안내에 따라 제시된 명령어를 복사하여 터미널에 붙여넣어 실행합니다.

pm2 startup

현재 PM2로 실행시킨 프로세스 목록을 저장해두면 나중에 AWS 인스턴스를 재시작해도 해당 앱을 실행시켜 줍니다. 이를 위해서는 다음과 같이 합니다. 현재는 이 작업이 이미 되어 있습니다.

pm2 save

만약에 Node.js 버전이 업데이트된 경우, pm2 unstartup으로 자동 시작을 해제한 뒤 다시 pm2 startup을 해줘야 합니다.

기타

  • Jenkins에서 빌드에 실패하는 경우, 마지막으로 성공한 빌드의 결과물을 재실행 없이 계속 실행합니다.
  • 서버 애플리케이션에서 MySQL에 의존하고 있으므로, MySQL과 연결되지 않으면 서버가 제대로 올라가지 않습니다.
  • 혹시 PM2가 아닌 다른 경로로 먼저 서버를 띄우면 8080 포트를 점유하므로 서버가 올라가는 데 문제가 생길 수 있습니다. 반대로, PM2에 의해 서버가 떠 있을 때 수동으로 서버를 띄우는 것도 안 될 겁니다.
  • 현재는 로그가 /home/ubuntu/ 디렉터리 및 그 하위의 .pm2/logs/에 저장되고 있습니다. 단, 빌드 후 테스트 때 출력된 로그는 /var/lib/jenkins/workspace/demo-test/에 저장되고 있습니다. 추후 로그 관련 설정을 변경하면 이 위치들은 바뀔 수 있습니다.