NodeJSのマスター・ワーカー・パターン解説

[![表紙](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/eeef0220-6ef4-2baa-6096-2076b4f02f11.png)](https://leapcell.io/?lc_t=q_nodemw)

NodeJS は、JavaScript を基盤とした開発プラットフォームで、開発者が JavaScript を使用してサーバーサイドアプリケーションを作成できるようにします。NodeJS の重要な特徴の一つは、シングルスレッドかつイベント駆動モデルで、多数の同時リクエストを効率的に処理できる点です。このモデルにより、複数のスレッドやプロセスを必要とせずに高いパフォーマンスを実現できます。

## マスターワーカーパターンを使用する理由

しかし、NodeJS のシングルスレッドモデルには以下のような制限があります。

- **CPU 集約型タスク**：画像処理や暗号化/復号化などのタスクでは、シングルスレッドが他のリクエストをブロックし、パフォーマンスが低下する可能性があります。
- **エラーハンドリング**：エラーや例外が発生した場合、シングルスレッドがクラッシュするとアプリケーション全体が停止する恐れがあります。
- **マルチコアの活用**：シングルスレッドモデルでは、マルチコア CPU の性能を十分に活用することができません。

これらの問題を解決するために、NodeJS ではマスターワーカーパターン（またはクラスター・モード）を提供しています。この分散システムデザインパターンは、マスタープロセスと複数のワーカープロセスで構成されます。マスタープロセスがワーカーを管理・監視し、ワーカープロセスは特定のビジネスロジックを処理します。

## マスターワーカーパターンの実装方法

NodeJS では、`cluster`モジュールを使用してマスターワーカーパターンを簡単に実装できます。このモジュールは、複数の子プロセスを作成し、それらを制御・通信するためのメソッドやイベントを提供します。基本的な使用手順は次の通りです。

1. `cluster`モジュールをインポートし、現在のプロセスがマスターかワーカーかを判定します。
2. マスターであれば、`cluster.fork()`メソッドを使用して複数のワーカープロセスを作成し、イベントをバインドして状態やメッセージを監視します。
3. ワーカーであれば、特定のビジネスロジックを実行し、`process.send()`を使用してマスタープロセスにメッセージを送信します。

## 基本的な使用例

以下は、`cluster`モジュールを使用した基本的な例です。

```javascript
const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;

if (cluster.isMaster) {
  console.log(`マスター ${process.pid} が実行中です`);

  // ワーカーをフォークする
  for (let i = 0; i < numCPUs; i++) {
    cluster.fork();
  }

  cluster.on('exit', (worker, code, signal) => {
    console.log(`ワーカー ${worker.process.pid} が終了しました`);
  });
} else {
  // ワーカーは任意のTCP接続を共有可能
  // この場合はHTTPサーバー
  http
    .createServer((req, res) => {
      res.writeHead(200);
      res.end('ワーカーからの応答です！');
    })
    .listen(8000);

  console.log(`ワーカー ${process.pid} が開始しました`);
}
```

このコードでは、マスタープロセスが`cluster.isMaster`をチェックし、マスターである場合はシステムの CPU コア数分だけワーカーを作成します。各ワーカーはマスタープロセスの独立したインスタンスであり、それぞれが独自のメモリと V8 インスタンスを持ちます。ワーカーは`http.createServer`を使用して HTTP サーバーを作成し、リクエストの待ち受けを開始します。

ワーカーがクラッシュまたは終了した場合、`exit`イベントがトリガーされ、マスターがそのワーカーを再起動することが可能です。

## 高度な使用例：Nginx による負荷分散の統合

Nginx をリバースプロキシおよびロードバランサーとして使用することで、複数の Node.js プロセス間でリクエストを分散できます。

Nginx の設定例：

```nginx
http {
    upstream node_cluster {
        server 127.0.0.1:8000;
        server 127.0.0.1:8001;
        server 127.0.0.1:8002;
        # ... その他のNode.jsプロセス
    }

    server {
        listen 80;

        location / {
            proxy_pass http://node_cluster;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection 'upgrade';
            proxy_set_header Host $host;
            proxy_cache_bypass $http_upgrade;
        }
    }
}
```

この設定では、Nginx が`node_cluster`内で定義された Node.js プロセス間でリクエストを均等に分散します。

## マスターワーカーパターンを使用する利点

- **負荷分散**：単一のサーバーで複数の Node.js プロセスを実行することで、リクエストが均等に分散され、スループットが向上します。
- **フォールトトレランスと高可用性**：ワーカーがクラッシュしても、マスターが他のワーカーに影響を与えずに再起動できます。
- **CPU 集約型タスク**：複数のワーカーが CPU 集約型タスクを処理することで、メインスレッドがブロックされるのを防ぎます。

## 注意点

- **状態の共有**：各ワーカープロセスは独立しており、メモリを共有しません。アプリケーションが状態の共有（例：セッション状態）を必要とする場合は、外部サービスやデータベースを使用する必要があります。

結論として、Node.js のマスターワーカーパターンは、`cluster`モジュールを通じて、マルチプロセスアプリケーションを簡単かつ効果的に構築できる方法を提供し、性能と信頼性を向上させます。

---

### [私たちはLeapcell、Node.jsプロジェクトのホスティングの最適解です](https://leapcell.io/?lc_t=q_nodemw)

[![Leapcell](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/6cfc5543-0c14-809c-f2d1-62fffb77d10e.png)](https://leapcell.io/?lc_t=q_nodemw)

[Leapcell](https://leapcell.io/?lc_t=q_nodemw)は、Webホスティング、非同期タスク、Redis向けの次世代サーバーレスプラットフォームです：

**複数言語サポート**

- Node.js、Python、Go、Rustで開発できます。

**無制限のプロジェクトデプロイ**

- 使用量に応じて料金を支払い、リクエストがなければ料金は発生しません。

**比類のないコスト効率**

- 使用量に応じた支払い、アイドル時間は課金されません。
- 例: $25で6.94Mリクエスト、平均応答時間60ms。

**洗練された開発者体験**

- 直感的なUIで簡単に設定できます。
- 完全自動化されたCI/CDパイプラインとGitOps統合。
- 実行可能なインサイトのためのリアルタイムのメトリクスとログ。

**簡単なスケーラビリティと高パフォーマンス**

- 高い同時実行性を容易に処理するためのオートスケーリング。
- ゼロ運用オーバーヘッド — 構築に集中できます。

[ドキュメントで詳細を確認！](https://docs.leapcell.io/)

[![Try Leapcell](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/689b1547-2574-2ff7-8189-f7b786fabc50.png)](https://leapcell.io/?lc_t=q_nodemw)

Xでフォローする：[@LeapcellHQ](https://x.com/LeapcellHQ)

---

[ブログでこの記事を読む](https://leapcell.io/blog/master-worker-pattern-in-nodejs)