PM2 clusterモードでNext.jsプロダクション性能を向上させる

問題

Node.jsはシングルスレッドのため、CPUコアが4つあっても1つしか使いません。トラフィックが集中すると、1つのプロセスがすべてを処理しなければなりません。

解決方法

// ecosystem.config.js
module.exports = {
  apps: [{
    name: 'my-app',
    script: 'node_modules/next/dist/bin/next',
    args: 'start --port 3000',
    instances: 2,           // CPUコア数分(または'max')
    exec_mode: 'cluster',   // clusterモード有効化
    max_memory_restart: '800M',
    env: {
      NODE_ENV: 'production',
    },
    // 再起動ポリシー
    exp_backoff_restart_delay: 100,
    max_restarts: 10,
    min_uptime: '10s',
    // ログ
    log_date_format: 'YYYY-MM-DD HH:mm:ss',
    merge_logs: true,
  }]
};
pm2 start ecosystem.config.js
pm2 monit    # リアルタイム監視
pm2 reload my-app  # ゼロダウンタイム再起動

ポイント

  • instances: 'max'にすると全コアを使いますが、Raspberry Piのような小型サーバーでは2つ程度に制限するのが安定的です。OSやRedisなど他のサービスにもコアが必要です。
  • exp_backoff_restart_delay: 100はアプリがクラッシュした際、100msから始めて段階的に間隔を広げて再起動します。無限再起動ループを防ぎます。
  • pm2 reloadrestartと異なり、プロセスを1つずつ順番に入れ替えるため、ダウンタイムがありません。