PM2とは
PM2とは、Node.js製のWebアプリケーションを動かすための仕組みの一つです。例えば、Express4などで作成したアプリ(app.js)を動かしたい場合に普通だと、
$ node app.js
として起動しますが、PM2を用いると、
$ pm2 start app.js
のような形式でWebサービスを起動することができます。
node app.js
での起動は非常にシンプルですが、以下のような問題点があります。
- 基本的にはCPU1コアしか使えず、マルチコアに対応するのに手間がかかる
- ログ出力や状態チェックなど自前で作る必要がある
- その他、本番運用のための細かな手間がある
などなど。PM2を用いると、例えばCPUコア数を自動的に考慮して複数インスタンスを起動してくれるなど、便利な点が多いです。
同様の本番環境で使える起動ツールとしては、foreverなどがありますが、最近ではPM2が便利でよく使われている印象です。
今回のコードの置き場
以下におきましたので、必要あればご参照いただけたら幸いです。
https://github.com/yoheiMune/node-playground/tree/master/010-pm2
今回は、以下のようなExpress4で作成された簡単なアプリケーションを例に、話を進めます。
// app.js
const express = require('express');
app = express();
app.get('/', (req, res) => {
res.send('Hello from index.');
});
app.listen(3000, () => {
console.log('Express app starts, linstening port on 3000.')
});
PM2のインストール
npm
から簡単にインストールすることが可能です。
# PM2をインストール
$ npm install -g pm2
インストール後に、以下のコマンドが認識されていればOKです。
$ pm2
PM2を使う
それではここから、pm2の基本的な使い方を見てみたいと思います。
起動する
起動するにはstart
コマンドを利用します。
(환경변수를 삽입해 pm2가동하기는 http://valuefactory.tistory.com/258?category=765146 참고)
# pm2 start [スクリプトファイルパス]
$ pm2 start app.js
[PM2] Starting /Users/munesadayohei/git/node-playground/010-pm2/app.js in fork_mode (1 instance)
[PM2] Done.
┌──────────┬────┬──────┬───────┬────────┬─────────┬────────┬─────┬───────────┬──────────┐
│ App name │ id │ mode │ pid │ status │ restart │ uptime │ cpu │ mem │ watching │
├──────────┼────┼──────┼───────┼────────┼─────────┼────────┼─────┼───────────┼──────────┤
│ app │ 0 │ fork │ 42728 │ online │ 0 │ 0s │ 0% │ 15.3 MB │ disabled │
└──────────┴────┴──────┴───────┴────────┴─────────┴────────┴─────┴───────────┴──────────┘
# --nameオプションをつけると、起動するアプリに名前をつけることができます。
# 今後の管理にも使うので、基本的には名前を明示的につけるのが良いです。
$ pm2 start app.js --name myapp
[PM2] Starting /Users/munesadayohei/git/node-playground/010-pm2/app.js in fork_mode (1 instance)
[PM2] Done.
┌──────────┬────┬──────┬───────┬────────┬─────────┬────────┬─────┬───────────┬──────────┐
│ App name │ id │ mode │ pid │ status │ restart │ uptime │ cpu │ mem │ watching │
├──────────┼────┼──────┼───────┼────────┼─────────┼────────┼─────┼───────────┼──────────┤
│ myapp │ 0 │ fork │ 42882 │ online │ 0 │ 0s │ 0% │ 13.4 MB │ disabled │
└──────────┴────┴──────┴───────┴────────┴─────────┴────────┴─────┴───────────┴──────────┘
再起動する
デプロイなどでコードが変わる場合に、restart
コマンドでサーバーを再起動して、変更を取り込むことができます。
# pm2 restart [アプリ名]
$ pm2 restart myapp
[PM2] Applying action restartProcessId on app [myapp](ids: 0)
[PM2] [myapp](0) ✓
┌──────────┬────┬──────┬───────┬────────┬─────────┬────────┬─────┬───────────┬──────────┐
│ App name │ id │ mode │ pid │ status │ restart │ uptime │ cpu │ mem │ watching │
├──────────┼────┼──────┼───────┼────────┼─────────┼────────┼─────┼───────────┼──────────┤
│ myapp │ 0 │ fork │ 43059 │ online │ 1 │ 0s │ 0% │ 15.2 MB │ disabled │
└──────────┴────┴──────┴───────┴────────┴─────────┴────────┴─────┴───────────┴──────────┘
ここでrestart
が1
に増えているからも、再起動されたことがわかります。
停止する
停止するためにはstop
コマンドを利用します。
# pm2 stop [アプリ名]
$ pm2 stop myapp
[PM2] Applying action stopProcessId on app [myapp](ids: 0)
[PM2] [myapp](0) ✓
┌──────────┬────┬──────┬─────┬─────────┬─────────┬────────┬─────┬────────┬──────────┐
│ App name │ id │ mode │ pid │ status │ restart │ uptime │ cpu │ mem │ watching │
├──────────┼────┼──────┼─────┼─────────┼─────────┼────────┼─────┼────────┼──────────┤
│ myapp │ 0 │ fork │ 0 │ stopped │ 1 │ 0 │ 0% │ 0 B │ disabled │
└──────────┴────┴──────┴─────┴─────────┴─────────┴────────┴─────┴────────┴──────────┘
Use `pm2 show ` to get more details about an app
ログの確認
logs
コマンドを用いることで、出力されているログを確認することができます。
# pm2 logs [アプリ名]
$ pm2 logs myapp
[TAILING] Tailing last 15 lines for [myapp] process (change the value with --lines option)
/Users/munesadayohei/.pm2/logs/myapp-error-0.log last 15 lines:
/Users/munesadayohei/.pm2/logs/myapp-out-0.log last 15 lines:
0|myapp | Express app starts, linstening port on 3000.
0|myapp | Express app starts, linstening port on 3000.
モニタリング
monit
コマンドを使うと、起動しているアプリのモニタリング(ログの確認やプロセスの確認)を行うことができます。
$ pm2 monit
クラスタリングモードでの起動
最初に説明したpm2 start [スクリプトファイルパス]
ではforkモードという状態で起動しますが、起動モードにはクラスターモードというものも存在します。フォークモードでは起動したアプリ自体がリクエストを受け取りますが、クラスターモードではpm2のマスターノードがリクエストを受け取り、それを起動中のインスタンスに割り振ります(いわゆるロードバランシングをしてくれます)。
この機能で、複数インスタンスを同時に立ち上げることで、マシンリソースを上限まで使うことができるようになります。具体的には、以下のように起動します。
# pm2 start [スクリプトファイル名] --name [名前] -i [起動数]
# -i をつけると、クラスターモードになり、起動数=0にすると、マシンのコア数でインスタンスを起動してくれる.
$ pm2 start app.js --name myapp -i 0
[PM2] Starting /Users/munesadayohei/git/node-playground/010-pm2/app.js in cluster_mode (0 instance)
[PM2] Done.
┌──────────┬────┬─────────┬───────┬────────┬─────────┬────────┬─────┬───────────┬──────────┐
│ App name │ id │ mode │ pid │ status │ restart │ uptime │ cpu │ mem │ watching │
├──────────┼────┼─────────┼───────┼────────┼─────────┼────────┼─────┼───────────┼──────────┤
│ myapp │ 0 │ cluster │ 43861 │ online │ 0 │ 0s │ 13% │ 26.5 MB │ disabled │
│ myapp │ 1 │ cluster │ 43862 │ online │ 0 │ 0s │ 30% │ 27.2 MB │ disabled │
│ myapp │ 2 │ cluster │ 43863 │ online │ 0 │ 0s │ 28% │ 26.8 MB │ disabled │
│ myapp │ 3 │ cluster │ 43864 │ online │ 0 │ 0s │ 25% │ 26.9 MB │ disabled │
└──────────┴────┴─────────┴───────┴────────┴─────────┴────────┴─────┴───────────┴──────────┘
今回のマシンの場合、4コアあるので、4つのクラスターが起動しています。クラスターモードで複数インスタンスを立ち上げておけば、restart
などで再起動する場合にも、ダウンタイム0で再起動することができます。
設定ファイルを用いた起動指定
起動オプションで便利な振る舞いを指定できますが、一度にたくさんを指定するのは面倒です。起動オプションは設定ファイル(YamlまたはJSON形式)で定義することもできます。その設定ファイルをstart
コマンドに渡すことで、便利なオプションを複数指定して起動することができます。
Yaml形式の場合
# ファイル名:pm2config.yml(ファイル名は自由です)
name: myapp # アプリ名
script: app.js # スクリプトファイルパス
exec_mode: "cluster" # 起動モード = cluster
instances: 0 # 起動インスタンス数
log-date-format: "YYYY-MM-DD HH:mm Z" # ログに日付を追加
JSONの場合
// ファイル名:pm2config.json(ファイル名は自由です)
{
"name": "myapp",
"script": "app.js",
"exec_mode": "cluster",
"instances": 0,
"log-date-format": "YYYY-MM-DD HH:mm Z"
}
基本的には、Yamlの方がシンプルだしコメントも書けるので、Yaml定義が良いなぁと思います。
上記の設定ファイルを用いて起動するには、以下のように行います。
# Yamlファイルを指定して、起動する場合
$ pm2 start pm2config.yml
# JSONファイルを指定して、起動する場合
$ pm2 start pm2config.json
参考資料
今回は、以下の公式資料を利用しました。他にも色々とコマンドが紹介されているので、一読する価値は高いです。
http://pm2.keymetrics.io/docs/usage/quick-start/
最後に
PM2は非常に便利で、他にも色々な使い方をしているので、その辺もブログにアウトプットしていきたいなと思います。
最後になりますが本ブログでは、Linux・インフラ・開発環境・Python・フロントエンド・Go言語・Node.js・Swift・Java・機械学習など雑多に情報発信をしていきます。自分の第2の脳にすべく、情報をブログに貯めています。気になった方は、本ブログのRSSやTwitterをフォローして頂けると幸いです ^ ^。
最後までご覧頂きましてありがとうございました!