T-CREATOR

Nginx キャパシティプランニング:worker_processes/connections/reuseport の算定メソッド

Nginx キャパシティプランニング:worker_processes/connections/reuseport の算定メソッド

Nginx のパフォーマンスチューニングを行う際、最も重要なパラメータの一つが worker_processesworker_connections、そして reuseport です。これらの設定値を適切に算定することで、サーバーのリソースを最大限に活用し、高い同時接続数やスループットを実現できます。

本記事では、これらのパラメータの算定メソッドを具体的な計算式とともに解説します。初めて Nginx のキャパシティプランニングに取り組む方でも理解できるよう、段階的に説明していきますね。

背景

Nginx のアーキテクチャとプロセスモデル

Nginx は非同期イベント駆動型のアーキテクチャを採用しており、少ないプロセス数で大量の同時接続を処理できる設計になっています。

このアーキテクチャの核となるのが、マスタープロセスと複数のワーカープロセスという構成です。マスタープロセスは設定ファイルの読み込みやワーカープロセスの管理を担当し、実際のリクエスト処理はワーカープロセスが行います。

以下の図は、Nginx のプロセスモデルと接続処理の流れを示しています。

mermaidflowchart TB
    master["マスタープロセス<br/>(設定管理・プロセス監視)"]
    worker1["ワーカープロセス 1<br/>(イベントループ)"]
    worker2["ワーカープロセス 2<br/>(イベントループ)"]
    worker3["ワーカープロセス N<br/>(イベントループ)"]

    client1["クライアント接続群<br/>(複数の同時接続)"]
    client2["クライアント接続群<br/>(複数の同時接続)"]
    client3["クライアント接続群<br/>(複数の同時接続)"]

    master --> worker1
    master --> worker2
    master --> worker3

    client1 -->|リクエスト| worker1
    client2 -->|リクエスト| worker2
    client3 -->|リクエスト| worker3

この図から分かるように、各ワーカープロセスは独立してクライアント接続を処理し、イベントループを使って効率的に複数の接続を管理しています。

キャパシティプランニングの重要性

Web サーバーの性能は、適切なキャパシティプランニングによって大きく左右されます。設定値が小さすぎると、サーバーの物理リソースを活用しきれず、パフォーマンスが低下してしまいます。

逆に設定値が大きすぎると、メモリ不足やコンテキストスイッチの増加により、かえって性能が悪化することもあるのです。そのため、サーバーのハードウェアスペックやトラフィック特性に応じた適切な設定が必要になります。

課題

よくある設定ミスとその影響

Nginx のキャパシティプランニングでは、以下のような課題に直面することが多いです。

CPU コア数と worker_processes の不一致

多くの場合、デフォルト設定のままで運用されており、サーバーの CPU コア数を十分に活用できていません。例えば、8 コアのサーバーで worker_processes 1 のままだと、1 つのコアしか使われず、残り 7 コアが遊んでしまいます。

メモリ制約を考慮しない worker_connections の設定

worker_connections を大きく設定しすぎると、接続ごとに確保されるメモリバッファが膨大になり、システムが不安定になる可能性があります。特に SSL/TLS 通信では、1 接続あたりのメモリ使用量が増えるため注意が必要です。

ファイルディスクリプタ制限の見落とし

OS レベルのファイルディスクリプタ上限(ulimit -n)を確認せずに worker_connections を設定すると、実際には設定値通りの接続数を処理できないことがあります。

以下の図は、設定ミスによって発生する問題の連鎖を示しています。

mermaidflowchart LR
    config["不適切な設定値"]
    cpu_waste["CPU リソースの<br/>未活用"]
    mem_issue["メモリ不足<br/>エラー"]
    fd_limit["ファイルディスクリプタ<br/>制限エラー"]
    perf_down["パフォーマンス低下<br/>接続拒否"]

    config -->|worker_processes<br/>が少なすぎる| cpu_waste
    config -->|worker_connections<br/>が大きすぎる| mem_issue
    config -->|ulimit を超える| fd_limit

    cpu_waste --> perf_down
    mem_issue --> perf_down
    fd_limit --> perf_down

図で理解できる要点:

  • 設定パラメータの不適切な値が、複数の問題を引き起こす
  • CPU、メモリ、ファイルディスクリプタそれぞれに適切な考慮が必要
  • 最終的にはパフォーマンス低下や接続拒否につながる

算定基準の不明確さ

初心者にとって最も難しいのは「何を基準に設定値を決めるべきか」という点です。インターネット上には様々な設定例が存在しますが、それらがなぜその値なのか、自分の環境に適用できるのかが分かりにくいのが現状です。

また、サーバーのスペックやトラフィックパターンは環境ごとに異なるため、汎用的な設定値をそのまま使うのは適切ではありません。

解決策

worker_processes の算定メソッド

worker_processes は、Nginx が起動するワーカープロセスの数を指定するパラメータです。この値の算定には、サーバーの CPU コア数を基準とします。

基本的な算定式

最もシンプルかつ効果的な設定方法は、CPU コア数と同じ値を設定することです。

nginx# CPU コア数を確認
# Linux の場合
bashnproc
# または
grep -c processor /proc/cpuinfo

上記のコマンドで CPU コア数を確認します。例えば、出力が 8 であれば、8 コアのシステムであることが分かります。

nginx# nginx.conf での設定例
worker_processes 8;

この設定により、各 CPU コアに 1 つのワーカープロセスが割り当てられ、CPU リソースを最大限に活用できます。

auto 設定の活用

Nginx 1.3.8 以降では、auto というキーワードを使用することで、自動的に CPU コア数を検出して設定できます。

nginx# 自動検出による設定
worker_processes auto;

この方法を使えば、サーバーを別の環境に移行した際も設定ファイルを変更する必要がなく、メンテナンス性が向上します。

CPU アフィニティの設定

各ワーカープロセスを特定の CPU コアに割り当てることで、キャッシュ効率を向上させることができます。

nginx# 8 コアシステムでの CPU アフィニティ設定
worker_processes 8;
worker_cpu_affinity 00000001 00000010 00000100 00001000
                    00010000 00100000 01000000 10000000;

worker_cpu_affinity では、各ワーカープロセスがどの CPU コアで実行されるかをビットマスクで指定します。最初のワーカーは 1 番目のコア、2 番目のワーカーは 2 番目のコア、という具合です。

より簡単な設定方法として、auto を使用することもできます。

nginx# 自動的に CPU アフィニティを設定
worker_processes auto;
worker_cpu_affinity auto;

worker_connections の算定メソッド

worker_connections は、1 つのワーカープロセスが同時に処理できる接続数の上限を指定します。この値の算定には、メモリ容量とファイルディスクリプタ制限の両方を考慮する必要があります。

ファイルディスクリプタ制限の確認

まず、OS レベルのファイルディスクリプタ制限を確認します。

bash# 現在のソフトリミットを確認
ulimit -n

例えば、この出力が 1024 の場合、1 プロセスあたり最大 1024 個のファイルを開けます。Nginx では、1 つのクライアント接続につき最低 2 つのファイルディスクリプタ(クライアント接続とバックエンドへの接続)が必要になることがあります。

ファイルディスクリプタ制限の拡張

Nginx で大量の同時接続を処理する場合は、この制限を拡張する必要があります。

bash# /etc/security/limits.conf に追加
nginx soft nofile 65535
nginx hard nofile 65535

システム全体の制限も確認しておきましょう。

bash# システム全体の制限を確認
cat /proc/sys/fs/file-max

必要に応じて、この値も増やします。

bash# /etc/sysctl.conf に追加
fs.file-max = 2097152

設定を反映させます。

bashsysctl -p
worker_connections の算定式

基本的な算定式は以下の通りです。

iniworker_connections = min(
  ファイルディスクリプタ制限 / 2,
  利用可能メモリ / (ワーカープロセス数 × 接続あたりメモリ使用量)
)

具体的な計算例を見てみましょう。

#項目
1ファイルディスクリプタ制限65535
2ワーカープロセス数8
3利用可能メモリ16 GB
4接続あたりメモリ使用量 (HTTP)約 5 KB
5接続あたりメモリ使用量 (HTTPS)約 15 KB

HTTP の場合の計算です。

textファイルディスクリプタ制限から: 65535 / 2 = 32767
メモリ制限から: (16 × 1024 × 1024 KB) / (8 × 5 KB) = 419430

worker_connections = min(32767, 419430) = 32767

この場合、ファイルディスクリプタがボトルネックとなるため、worker_connections 32768 程度が適切です(2 の累乗に合わせて調整)。

HTTPS の場合は、メモリ使用量が増えるため再計算が必要です。

textメモリ制限から: (16 × 1024 × 1024 KB) / (8 × 15 KB) = 139810

worker_connections = min(32767, 139810) = 32767
実際の nginx.conf 設定

計算結果を基に、実際の設定を行います。

nginxevents {
    worker_connections 16384;
    use epoll;  # Linux の場合
}

worker_connections の値は、安全マージンを考慮して計算値より若干小さめに設定することをお勧めします。上記の例では、32768 に対して 16384 を設定しています。

reuseport の算定メソッド

reuseport は、複数のワーカープロセスが同じポートでリスニングできるようにするオプションです。これにより、カーネルレベルでの負荷分散が可能になり、パフォーマンスが向上します。

reuseport の仕組み

通常、Nginx では全ワーカープロセスが共有のリスニングソケットを使用します。新しい接続が来ると、マスタープロセスが accept ロックを使ってワーカープロセス間で調停を行います。

reuseport を有効にすると、各ワーカープロセスが独自のリスニングソケットを持ち、カーネルが接続を各ワーカーに分散します。

以下の図は、reuseport 有効時と無効時の接続処理の違いを示しています。

mermaidflowchart TB
    subgraph without["reuseport 無効"]
        socket1["共有リスニング<br/>ソケット"]
        lock["Accept ロック<br/>(競合制御)"]
        w1["ワーカー 1"]
        w2["ワーカー 2"]
        w3["ワーカー 3"]

        socket1 --> lock
        lock --> w1
        lock --> w2
        lock --> w3
    end

    subgraph with["reuseport 有効"]
        kernel["カーネルレベル<br/>負荷分散"]
        s1["ソケット 1"]
        s2["ソケット 2"]
        s3["ソケット 3"]
        wk1["ワーカー 1"]
        wk2["ワーカー 2"]
        wk3["ワーカー 3"]

        kernel --> s1
        kernel --> s2
        kernel --> s3
        s1 --> wk1
        s2 --> wk2
        s3 --> wk3
    end

図で理解できる要点:

  • reuseport 無効時は、Accept ロックによる競合が発生する
  • reuseport 有効時は、カーネルが直接各ワーカーに接続を分散する
  • reuseport により、ロック競合のオーバーヘッドが削減される
reuseport の設定条件

reuseport を有効にすべきケースは以下の通りです。

#条件説明
1ワーカープロセス数が多い4 プロセス以上で効果が顕著
2高トラフィック環境毎秒数千〜数万リクエスト
3短い接続が多いKeep-Alive が短い、または使われない
4カーネルバージョンLinux 3.9 以降、または対応 OS

逆に、以下の場合は reuseport の効果が限定的です。

  • ワーカープロセス数が少ない(1〜2 プロセス)
  • 長時間の Keep-Alive 接続が主体
  • トラフィックが少ない環境
reuseport の有効化

listen ディレクティブに reuseport オプションを追加します。

nginxhttp {
    server {
        listen 80 reuseport;
        listen [::]:80 reuseport;

        # HTTPS の場合
        listen 443 ssl http2 reuseport;
        listen [::]:443 ssl http2 reuseport;

        server_name example.com;
        # 以降の設定
    }
}

複数の server ブロックがある場合、最初の server ブロックの listen ディレクティブにのみ reuseport を指定します。

パフォーマンス測定による判断

reuseport の効果は環境によって異なるため、実際に測定して判断することが重要です。

負荷テストツールを使って、有効時と無効時のスループットを比較します。

bash# Apache Bench での測定例
ab -n 100000 -c 1000 http://localhost/
text# 測定指標
- Requests per second (RPS)
- Time per request
- Failed requests
#測定項目reuseport 無効reuseport 有効改善率
1RPS25000 req/s32000 req/s+28%
2レイテンシ (平均)40 ms31 ms-22%
3CPU 使用率85%78%-8%

このような測定結果が得られれば、reuseport を有効にする価値があると判断できます。

具体例

小規模 Web サイトの設定例

ここでは、実際の環境を想定した具体的な設定例を紹介します。まずは、小規模な Web サイトのケースから見ていきましょう。

システムスペック
#項目
1CPU2 コア
2メモリ4 GB
3想定同時接続数500 接続
4プロトコルHTTP のみ
算定プロセス

ステップ 1: worker_processes の決定

CPU コア数が 2 なので、worker_processes は 2 に設定します。

nginxworker_processes 2;
worker_cpu_affinity 01 10;

ステップ 2: ファイルディスクリプタ制限の確認

bashulimit -n
# 出力例: 1024

ステップ 3: worker_connections の算定

想定同時接続数が 500 で、ワーカープロセスが 2 つなので、1 ワーカーあたり 250 接続を処理できれば十分です。ただし、余裕を持たせて 1024 に設定します。

text必要な worker_connections = 500 / 2 = 250
安全マージンを考慮: 1024

ステップ 4: メモリ使用量の検証

text総メモリ使用量 = ワーカー数 × worker_connections × 接続あたりメモリ
                = 2 × 1024 × 5 KB
                = 10240 KB
                ≈ 10 MB

4 GB のメモリに対して 10 MB は十分に小さいため、問題ありません。

ステップ 5: reuseport の判断

ワーカープロセス数が 2 と少なく、想定トラフィックも小規模なため、reuseport は不要と判断します。

最終的な nginx.conf

上記の算定結果を基に、実際の設定ファイルを作成します。

nginx# メインコンテキスト
user nginx;
worker_processes 2;
worker_cpu_affinity 01 10;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
nginx# イベントコンテキスト
events {
    worker_connections 1024;
    use epoll;
}
nginx# HTTP コンテキスト
http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    sendfile on;
    keepalive_timeout 65;

    server {
        listen 80;
        server_name example.com;

        location / {
            root /usr/share/nginx/html;
            index index.html;
        }
    }
}

この設定により、2 コア 4 GB のサーバーで効率的に小規模トラフィックを処理できます。

大規模 Web サービスの設定例

次に、大規模な Web サービスを想定した設定例を見てみましょう。

システムスペック
#項目
1CPU32 コア
2メモリ128 GB
3想定同時接続数50000 接続
4プロトコルHTTPS (HTTP/2)
算定プロセス

ステップ 1: worker_processes の決定

CPU コア数が 32 なので、基本的には 32 ワーカーを起動します。

nginxworker_processes auto;  # 32 として自動設定される
worker_cpu_affinity auto;

ステップ 2: ファイルディスクリプタ制限の拡張

大量の同時接続を処理するため、制限を拡張します。

bash# /etc/security/limits.conf
nginx soft nofile 65535
nginx hard nofile 65535
bash# /etc/sysctl.conf
fs.file-max = 2097152

システムに反映させます。

bashsysctl -p

ステップ 3: worker_connections の算定

HTTPS 接続の場合、1 接続あたり約 15 KB のメモリを使用します。

textファイルディスクリプタ制限から:
  65535 / 2 = 32767

メモリ制限から:
  (128 × 1024 × 1024 KB) / (32 × 15 KB)
  = 134217728 / 480
  = 279620

worker_connections = min(32767, 279620) = 32767

ただし、実際の運用では安全マージンを考慮して 16384 に設定します。

text総同時接続数 = 32 × 16384 = 524288 接続

これは想定の 50000 接続を大きく上回るため、十分な容量です。

ステップ 4: reuseport の有効化

ワーカープロセス数が 32 と多く、高トラフィック環境のため、reuseport を有効にします。

以下の図は、大規模環境でのリクエスト処理フローを示しています。

mermaidsequenceDiagram
    participant Client as クライアント
    participant LB as ロードバランサー
    participant Kernel as カーネル<br/>(reuseport)
    participant W1 as ワーカー 1
    participant W2 as ワーカー 2
    participant Backend as バックエンド

    Client->>LB: HTTPS リクエスト
    LB->>Kernel: 接続転送

    alt ワーカー 1 に分散
        Kernel->>W1: 接続割り当て
        W1->>Backend: API 呼び出し
        Backend->>W1: レスポンス
        W1->>Client: HTTPS レスポンス
    else ワーカー 2 に分散
        Kernel->>W2: 接続割り当て
        W2->>Backend: API 呼び出し
        Backend->>W2: レスポンス
        W2->>Client: HTTPS レスポンス
    end
最終的な nginx.conf

大規模環境向けの設定を構築します。

nginx# メインコンテキスト
user nginx;
worker_processes auto;
worker_cpu_affinity auto;
worker_rlimit_nofile 65535;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
nginx# イベントコンテキスト
events {
    worker_connections 16384;
    use epoll;
    multi_accept on;
}

multi_accept on を設定することで、1 回のイベントループで複数の新規接続を受け入れられます。これにより、高トラフィック時のパフォーマンスが向上します。

nginx# HTTP コンテキスト
http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    # ログフォーマット
    log_format main '$remote_addr - $remote_user [$time_local] '
                    '"$request" $status $body_bytes_sent '
                    '"$http_referer" "$http_user_agent"';

    access_log /var/log/nginx/access.log main;
nginx    # パフォーマンス最適化
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    keepalive_requests 100;

    # バッファサイズ設定
    client_body_buffer_size 128k;
    client_max_body_size 10m;
    client_header_buffer_size 1k;
    large_client_header_buffers 4 8k;
nginx    # gzip 圧縮
    gzip on;
    gzip_vary on;
    gzip_min_length 1000;
    gzip_types text/plain text/css application/json
               application/javascript text/xml application/xml;
nginx    # アップストリーム設定
    upstream backend {
        server backend1.example.com:8080;
        server backend2.example.com:8080;
        keepalive 32;
    }
nginx    # HTTPS サーバー
    server {
        listen 443 ssl http2 reuseport;
        listen [::]:443 ssl http2 reuseport;
        server_name api.example.com;

        # SSL 証明書
        ssl_certificate /etc/nginx/ssl/certificate.crt;
        ssl_certificate_key /etc/nginx/ssl/private.key;

        # SSL 設定
        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_ciphers HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers on;
        ssl_session_cache shared:SSL:10m;
        ssl_session_timeout 10m;
nginx        # ロケーション設定
        location /api/ {
            proxy_pass http://backend;
            proxy_http_version 1.1;
            proxy_set_header Connection "";
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }

        location / {
            root /usr/share/nginx/html;
            index index.html;
            try_files $uri $uri/ =404;
        }
    }
nginx    # HTTP から HTTPS へのリダイレクト
    server {
        listen 80;
        listen [::]:80;
        server_name api.example.com;

        return 301 https://$server_name$request_uri;
    }
}

この設定により、32 コア 128 GB のサーバーで、50000 以上の同時 HTTPS 接続を効率的に処理できます。

チューニング後の検証方法

設定を適用した後は、必ず性能測定を行って効果を検証しましょう。

負荷テストの実施

Apache Bench を使った基本的な負荷テストです。

bash# 10 万リクエスト、同時接続数 1000 でテスト
ab -n 100000 -c 1000 https://api.example.com/

より高度な負荷テストには、wrk を使用します。

bash# 30 秒間、12 スレッド、400 接続で負荷テスト
wrk -t12 -c400 -d30s https://api.example.com/
モニタリング指標の確認

Nginx のステータスモジュールを有効にして、リアルタイムで接続状況を監視します。

nginx# nginx.conf に追加
server {
    listen 127.0.0.1:8080;

    location /nginx_status {
        stub_status on;
        access_log off;
        allow 127.0.0.1;
        deny all;
    }
}

ステータス情報を確認します。

bashcurl http://127.0.0.1:8080/nginx_status
text# 出力例
Active connections: 1523
server accepts handled requests
 1234567 1234567 9876543
Reading: 12 Writing: 345 Waiting: 1166

各指標の意味は以下の通りです。

#指標意味
1Active connections現在のアクティブ接続数
2accepts受け入れた接続の総数
3handled処理した接続の総数
4requestsクライアントリクエストの総数
5Readingリクエストヘッダーを読み取り中の接続数
6Writingレスポンスをクライアントに送信中の接続数
7WaitingKeep-Alive で次のリクエストを待機中の接続数

これらの値を監視することで、設定が適切かどうかを判断できます。

まとめ

Nginx のキャパシティプランニングでは、worker_processesworker_connectionsreuseport の 3 つのパラメータを適切に設定することが重要です。

worker_processes の算定ポイント

CPU コア数に合わせて設定し、auto キーワードを使うことでメンテナンス性を向上させることができます。worker_cpu_affinity も併せて設定することで、キャッシュ効率が高まります。

worker_connections の算定ポイント

ファイルディスクリプタ制限とメモリ容量の両方を考慮して算出する必要があります。HTTPS 通信の場合は、メモリ使用量が増えるため、HTTP の約 3 倍のメモリを見積もってください。

安全マージンを持たせて、計算値の 50〜70% 程度に設定すると安定運用できます。

reuseport の判断ポイント

ワーカープロセス数が 4 以上で、高トラフィック環境の場合に有効化を検討しましょう。実際の効果は環境によって異なるため、負荷テストで測定して判断することが大切です。

継続的な最適化

一度設定したら終わりではなく、トラフィックの変化に応じて定期的に見直すことが重要です。モニタリングツールを活用して、常にサーバーの状態を把握し、ボトルネックを早期に発見できる体制を整えましょう。

適切なキャパシティプランニングにより、Nginx のパフォーマンスを最大限に引き出し、安定したサービス提供が可能になります。

関連リンク