2026年6月29日

2026年6月29日

Nginxのロードバランシング設定方法(upstreamの書き方・分散方式・障害時の切り離し)

Nginxで負荷分散を行うには、upstream ブロックにバックエンドのサーバーを並べ、proxy_pass でそのグループ名を指定します。この記事では、基本の設定、分散方式(ラウンドロビン・least_conn・ip_hash・hash)の選び方、重み付けと障害時の切り離し、キープアライブの設定、そしてWordPressを複数台に分けるときに先に解決しておくべき点を説明します。リバースプロキシの基本(proxy_set_header など)は理解している前提で進めます。

基本の設定

2台のアプリケーションサーバーに振り分ける例です。upstream は http の階層(server の外)に書きます。

upstream app_backend {
    server 10.0.0.11:8080;
    server 10.0.0.12:8080;
}

server {
    listen 80;
    server_name www.example.com;

    location / {
        proxy_pass http://app_backend;
        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;
    }
}

何も指定しなければ、リクエストは順番に各サーバーへ割り振られます(ラウンドロビン)。設定を変えたら sudo nginx -t で構文を確認し、sudo systemctl reload nginx で反映します。再読み込みは処理中の接続を切らずに新しい設定へ切り替えるため、運用中でも使えます。

分散方式の選び方

分散方式は upstream ブロックの先頭に1行書いて切り替えます。

upstream app_backend {
    least_conn;
    server 10.0.0.11:8080;
    server 10.0.0.12:8080;
}
  • ラウンドロビン(指定なし): 1件ずつ順番に振り分けます。各リクエストの処理時間がそろっている場合に向いています。
  • least_conn: その時点で処理中の接続が少ないサーバーを選びます。重い処理と軽い処理が混ざるアプリケーションでは、ラウンドロビンより偏りが出にくくなります。
  • ip_hash: 接続元IPアドレスから振り分け先を決めるため、同じ利用者は同じサーバーに届きます。サーバー側にセッションを持つアプリケーションの応急処置に使えますが、会社や携帯回線のように多くの人が同じIPを共有すると偏ります。
  • hash キー [consistent]: 指定した値(例: $request_uri)から振り分け先を決めます。consistent を付けると、サーバーを増減したときに振り分け先が変わるキーの数を抑えられます。キャッシュサーバーを並べる場合に使われます。

なお、NginxにはOSS版と商用のNGINX Plusがあり、一部の方式や機能はNGINX Plusだけで提供されています。公式ドキュメントで「commercial subscription」と書かれた項目は、OSS版では使えません(2026年10月現在)。

重み付けと障害時の切り離し

性能の違うサーバーを混ぜる場合や、1台を予備にしたい場合は、server 行にパラメーターを付けます。

upstream app_backend {
    server 10.0.0.11:8080 weight=3 max_fails=3 fail_timeout=30s;
    server 10.0.0.12:8080 weight=1 max_fails=3 fail_timeout=30s;
    server 10.0.0.13:8080 backup;
}
  • weight=3: 他のサーバーの3倍の割合でリクエストを受けます。既定値は1です。
  • max_fails と fail_timeout: fail_timeout の時間内に max_fails 回失敗すると、そのサーバーを fail_timeout の間だけ使わなくなります。既定値はそれぞれ1回と10秒です。
  • backup: 他のサーバーがすべて使えないときだけ使われます。hash・ip_hash・random の方式とは組み合わせられません。
  • down: 一時的に外すときに付けます。メンテナンスで1台を止める前に down を付けて再読み込みすると、新しいリクエストが届かなくなります。

OSS版のNginxが行うのは、実際のリクエストが失敗したかどうかで判断する「受け身の」ヘルスチェックです。定期的にバックエンドへ確認用のリクエストを送る能動的なヘルスチェック(health_check)はNGINX Plusの機能です。OSS版で能動的な監視が必要なら、外部の監視ツールでバックエンドを見張り、異常時に down を付ける運用を組み合わせます。

失敗したリクエストの再送

あるサーバーで接続エラーやタイムアウトが起きると、Nginxは同じリクエストを次のサーバーに送り直します。どの失敗で再送するかは proxy_next_upstream で決まり、既定値は error timeout です。

location / {
    proxy_pass http://app_backend;
    proxy_next_upstream error timeout http_502 http_503;
    proxy_next_upstream_tries 2;
}

POSTのように同じ処理を2回行うと困るリクエストは、既定ではバックエンドに送った後の失敗では再送されません(non_idempotent を付けると再送されます)。注文や決済のような処理を扱う場合、この指定は付けないままにしておくのが安全です。proxy_next_upstream_tries で再送の回数に上限を付けておくと、全台が遅いときに待ち時間が積み重なるのを防げます。

バックエンドとの接続を使い回す

既定では、Nginxはリクエストごとにバックエンドへの接続を作り直します。アクセスが多いと接続の確立に時間とポートを使うため、キープアライブで接続を使い回します。

upstream app_backend {
    server 10.0.0.11:8080;
    server 10.0.0.12:8080;
    keepalive 32;
}

server {
    location / {
        proxy_pass http://app_backend;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_set_header Host $host;
    }
}

keepalive 32 は、ワーカープロセスごとに待機させておく接続の上限で、同時接続数の上限ではありません。proxy_http_version 1.1 と、Connection ヘッダーを空にする指定の両方が必要です。

どのサーバーに振り分けられたかを確認する

設定が意図どおりに動いているかは、アクセスログに振り分け先を記録すると分かります。log_format も http の階層に書きます。

log_format upstreamlog '$remote_addr [$time_local] "$request" $status '
                       'upstream=$upstream_addr rt=$request_time urt=$upstream_response_time';
access_log /var/log/nginx/lb_access.log upstreamlog;

何度かアクセスしてから tail でログを見ると、upstream= の値が切り替わっていることを確認できます。1台を止めたときに、残りのサーバーへ流れることも試しておきます。再送が起きたリクエストでは、$upstream_addr に複数のアドレスがカンマ区切りで記録されます。

WordPressを複数台に分ける前に解決すること

Nginxの設定だけでは、WordPressは複数台で正しく動きません。次の点を先に決めておきます。

  1. データベースは共有する: すべてのサーバーが同じデータベースに接続します。各サーバーにデータベースを置くと内容がずれます。
  2. アップロードしたファイルを共有する: 1台にアップロードした画像が他のサーバーに無いと、表示されたりされなかったりします。共有ストレージや、メディアをオブジェクトストレージに置くプラグインで解決します。
  3. 設定とコードをそろえる: wp-config.php の認証用キーとソルトが違うと、サーバーが変わるたびにログインが切れます。プラグインやテーマの更新も全台で同時に反映する仕組みが必要です。
  4. オブジェクトキャッシュを共有する: Redisなどを使う場合は、各サーバーから同じキャッシュを参照させます。
  5. WP-Cronを1か所で動かす: 全台でアクセス契機の予約処理が走るのを避けるため、DISABLE_WP_CRON を設定し、1台のcronから実行する方法がよく使われます。

この準備を飛ばして ip_hash で同じサーバーに固定する方法もありますが、そのサーバーが止まると同じ問題が表に出ます。構成を変える前にバックアップを取り、ステージング環境で動作を確かめてから本番に移します。

まとめ

  • upstream にサーバーを並べ、proxy_pass でグループ名を指定すると負荷分散になります。既定はラウンドロビンです。
  • 処理時間がばらつくなら least_conn、利用者を同じサーバーに固定したいなら ip_hash や hash を検討します。
  • max_fails・fail_timeout・backup・down で障害時とメンテナンス時の動きを決めます。OSS版のヘルスチェックは受け身です。
  • POSTなどの再送は既定で抑えられています。注文や決済を扱うなら変えないでおきます。
  • WordPressでは、データベース・アップロードファイル・キー・キャッシュ・WP-Cronを共有または1か所にまとめてから台数を増やします。

お気軽にご相談ください

お見積りへ お問い合わせへ
▲