PM2を使ってNodeサーバを永続化する
はじめに
当社は以前の記事「Raspberry Pi でWebサーバを立てよう【Node.js】」でNodeサーバを使ったwebシステムを紹介しました。
実はこれには欠点があり、この方法で作ったwebサーバは予期しないエラーが発生したときにサーバ自体が落ちてしまいます。
そんな問題を防ぐために、作ったNodeサーバをPM2で永続化する方法をご紹介したいと思います。
PM2とは
PM2はアプリケーションを永続化し、異常終了した場合にアプリケーションの再始動を行ってくれるプロセス管理のアプリケーションです。
また、コンソールの内容を通常時と異常発生時を分けて、自動でログとして保存する機能もあります。
使い方
まずはコマンドを立ち上げ、PM2をインストールします。
npm install pm2 -g
インストールが完了後、立ち上げたいNodeサーバをpm2コマンドで立ち上げます。
pm2 start app.js //立ち上げたいNodeサーバ
これで簡単にNodeサーバを永続化させることができます。
永続化したNodeサーバを止める場合には以下のコマンドを入力します。
pm2 stop app.js //止めたいNodeサーバ
PM2を使ってみる
実際にPM2を使って動かしてみます。
まずはExpress-Generatorを使ってWebサーバを立ち上げます。(参考はこちら)
express testweb --view=pug
routes/index.jsを以下のように書き換えます。
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
router.get('/serverdown', async function(req, res, next){
console.log("start")
work() //存在しないwork関数を呼び出す
res.json({
})
});
module.exports = router;
これでhttp://localhost:3000/serverdownにアクセスすると、存在しない関数を呼び出してエラーが発生するようになりました。
このサーバをPM2を使って起動した場合と、PM2を使わないで起動した場合でエラーが起きた時の動きを比べてみます。
PM2を使わないで起動した場合
npm startでNodeサーバを起動します。
C:\test_web>npm start
> test-web@0.0.0 start
> node ./bin/www
サーバが起動後にブラウザからhttp://localhost:3000/serverdownにアクセスします。
ブラウザがこのサイトにアクセスできない表示になりました。
ブラウザからhttp://localhost:3000にアクセスしても変わらずページは表示されません。
コンソールを見ると、エラーが表示されサーバが落ちていることが確認できます。
こうなってしまうと再びサーバを起動するまでwebページにアクセスすることはできません。
PM2を使って起動した場合
今度はPM2を使ってwebサーバを立ち上げた場合を試してみます。
先ほど作ったNodeサーバをPM2を使って起動します。
C:\test_web>pm2 start bin/www
[PM2] Spawning PM2 daemon with pm2_home=C:\Users\user\.pm2
[PM2] PM2 Successfully daemonized
[PM2] Starting C:\test_web\bin\www in fork_mode (1 instance)
[PM2] Done.
┌─────┬────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──────────┬──────────┐
│ id │ name │ namespace │ version │ mode │ pid │ uptime │ ↺ │ status │ cpu │ mem │ user │ watching │
├─────┼────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──────────┼──────────┤
│ 0 │ www │ default │ 0.0.0 │ fork │ 11036 │ 0s │ 0 │ online │ 0% │ 30.3mb │ user │ disabled │
└─────┴────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──────────┴──────────┘
起動後、同じようにブラウザからhttp://localhost:3000/serverdownにアクセスしてみます。
今度はブラウザがアクセスできない状態にならず、読み込み中のままになります。
その後ブラウザからhttp://localhost:3000にアクセスするとExpressのサンプルページが表示され、正常にアクセスできることが確認できます。
次はコンソールを確認してみますが、PM2でサーバを起動した場合はコンソールにメッセージを出さないのでエラーを確認することはできません。
そこで、PM2が作成するwww-error.logを見るとエラーが発生したことを確認できます。
ReferenceError: work is not defined
at C:\test_web\routes\index.js:12:5
at Layer.handle [as handle_request] (C:\test_web\node_modules\express\lib\router\layer.js:95:5)
at next (C:\test_web\node_modules\express\lib\router\route.js:137:13)
at Route.dispatch (C:\test_web\node_modules\express\lib\router\route.js:112:3)
at Layer.handle [as handle_request] (C:\test_web\node_modules\express\lib\router\layer.js:95:5)
at C:\test_web\node_modules\express\lib\router\index.js:281:22
at Function.process_params (C:\test_web\node_modules\express\lib\router\index.js:335:12)
at next (C:\test_web\node_modules\express\lib\router\index.js:275:10)
at Function.handle (C:\test_web\node_modules\express\lib\router\index.js:174:3)
at router (C:\test_web\node_modules\express\lib\router\index.js:47:12)
PM2を使ったことで、エラーが発生しても再びサーバが起動していることが分かりました。
この動きの中で、http://localhost:3000/serverdownにアクセスしたときにエラーが発生し、一度サーバが落ちて反応を返さなくなり、読み込み中のままになっていました。
その時、PM2がサーバが落ちたのを検知し、サーバを再始動させたのでエラーが起きた後でもhttp://localhost:3000にアクセスするとwebページを見ることができます。
おわりに
PM2を使ってNodeサーバを永続化する方法をご紹介しました。
PM2を使うことでエラーが起きてもサーバが落ちるのを防ぐことができます。
落ちないサーバを作るのが一番ですが、エラーを完全に防ぐことは難しいときもあります。
そういった場合の対策として試してみてはいかがでしょうか。