Nginxリバースプロキシ設定で複数バックエンドを効率的に統合する

本記事では、Nginxのリバースプロキシ機能を実装し、複数のバックエンドサーバーへのリクエスト振り分けと負荷分散を実現する実践的な設定方法を解説します。設定ファイルの具体例とトラブルシューティングにより、本番環境でそのまま活用できる知識を習得できます。

Nginxリバースプロキシとは

Nginxのリバースプロキシは、クライアントからのリクエストを受け取り、バックエンドのアプリケーションサーバーに転送し、レスポンスを返すミドルウェアです。単なるリクエスト転送だけでなく、複数サーバーへの負荷分散、キャッシング、SSL/TLS終端、HTTPヘッダーの操作など、本番環境で必須の機能を提供します。

使うべき場面: Webアプリケーションのスケーリング、複数マイクロサービスの統合、レイテンシー削減が必要な場合。使うべきでない場面: シンプルな静的サイト配信、または学習段階でまず不要な複雑性を避けたい場合。

基本的なリバースプロキシ設定

最小構成の設定例

最初に、単一のバックエンドサーバーへのリバースプロキシ設定を見てみましょう。以下は/etc/nginx/nginx.confまたはサイト設定ファイル/etc/nginx/sites-available/defaultに記述する例です。

upstream backend {
    server 127.0.0.1:8080;
}

server {
    listen 80;
    server_name example.com;

    location / {
        # バックエンドサーバーにリクエストを転送
        proxy_pass http://backend;
        
        # クライアントのIPアドレスを保持
        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;
        
        # ホスト情報を正しく設定
        proxy_set_header Host $host;
        
        # タイムアウト設定(秒単位)
        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }
}

設定項目の詳細解説

upstreamブロックはバックエンドサーバーのグループを定義します。複数のサーバーをここに列挙することで、Nginxが自動的に負荷分散します。proxy_set_headerはバックエンドサーバーに送信するHTTPヘッダーをカスタマイズします。特にX-Real-IPX-Forwarded-Forはクライアントの本来のIPアドレスを保持するために必須です。

複数バックエンドサーバーへの負荷分散設定

ラウンドロビン負荷分散

複数のバックエンドサーバーがある場合、デフォルトではラウンドロビン方式でリクエストが分散されます。以下の設定を試してみてください。

upstream backend_servers {
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
    server 192.168.1.12:8080;
}

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://backend_servers;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

重み付け負荷分散(重要なサーバーに優先度を付与)

サーバーのスペックが異なる場合、weightパラメータで処理能力に応じた配分が可能です。

upstream backend_servers {
    server 192.168.1.10:8080 weight=3;  # 60%のトラフィック
    server 192.168.1.11:8080 weight=2;  # 40%のトラフィック
}

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://backend_servers;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

セッション保持(Sticky Session)

特定のクライアントを常に同じバックエンドサーバーにルーティングする必要がある場合、以下の設定を使用します。

upstream backend_servers {
    # IPハッシュに基づいてセッション保持
    ip_hash;
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
    server 192.168.1.12:8080;
}

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://backend_servers;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

ヘルスチェックと障害時の自動フェイルオーバー

本番環境ではバックエンドサーバーが予期なく停止することがあります。Nginx Plusでは高度なヘルスチェックが利用できますが、オープンソース版でも基本的なフェイルオーバーが可能です。

オープンソース版での基本的なフェイルオーバー

upstream backend_servers {
    server 192.168.1.10:8080 max_fails=3 fail_timeout=30s;
    server 192.168.1.11:8080 max_fails=3 fail_timeout=30s;
    server 192.168.1.12:8080 backup;  # メインサーバーが全て落ちた時のみ使用
}

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://backend_servers;
        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_next_upstream error timeout http_502 http_503;
        proxy_next_upstream_tries 2;
    }
}

max_fails=3は3回の失敗でサーバーを一時的に利用不可とし、fail_timeout=30sは30秒後に復帰を試みます。backupキーワードでスタンバイサーバーを指定できます。

パス別ルーティング設定

異なるアプリケーションへのリクエスト振り分け

同じドメイン内で異なるパスのリクエストを異なるバックエンドに振り分ける実装例を見てみましょう。

upstream api_backend {
    server 192.168.1.20:3000;
}

upstream web_backend {
    server 192.168.1.21:8080;
}

upstream admin_backend {
    server 192.168.1.22:9000;
}

server {
    listen 80;
    server_name example.com;

    # APIリクエストのルーティング
    location /api/ {
        proxy_pass http://api_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;
    }

    # 管理画面へのルーティング
    location /admin/ {
        proxy_pass http://admin_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;
    }

    # その他のリクエスト(Webアプリケーション)
    location / {
        proxy_pass http://web_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;
    }
}

よくあるトラブルシューティング

502 Bad Gatewayエラーが頻発する場合

原因1: バックエンドサーバーがダウンしている
curl http://192.168.1.10:8080でバックエンドサーバーの応答を確認してください。

原因2: タイムアウト設定が短すぎる
proxy_read_timeoutproxy_connect_timeoutを増やしてみてください。特に重い処理を扱う場合は90秒以上に設定することをお勧めします。

proxy_connect_timeout 90s;
proxy_send_timeout 90s;
proxy_read_timeout 90s;

原因3: ホストヘッダーが正しく設定されていない
バックエンドがホストベースのバーチャルホストを使用している場合、proxy_set_header Host $host;が必須です。

クライアントの実IPが取得できない場合

バックエンドアプリケーションがX-Forwarded-Forヘッダーを認識していない可能性があります。設定が正しいことを確認したら、アプリケーション側でこのヘッダーを読むよう修正が必要です。

WebSocketやLong Pollingが動作しない場合

WebSocket通信にはアップグレード用の追加ヘッダーが必要です。

location /ws/ {
    proxy_pass http://backend_servers;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    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_read_timeout 86400;  # WebSocket用に長めに設定
}

設定の検証と反映

設定ファイルの文法チェックと反映は以下のコマンドで実行します。

# 設定ファイルの文法検証
sudo nginx -t

# 正常ならこのメッセージが表示される
# nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
# nginx: configuration file /etc/nginx/nginx.conf test is successful

# 設定の再読み込み(ダウンタイムなし)
sudo systemctl reload nginx

# またはシグナルを使用
sudo kill -HUP $(cat /var/run/nginx.pid)

パフォーマンスチューニング

バッファ設定の最適化

大規模なレスポンスを扱う場合、バッファ設定がパフォーマンスに影響します。

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://backend_servers;
        
        # バックエンドのレスポンスをメモリにバッファする
        proxy_buffering on;
        proxy_buffer_size 4k;
        proxy_buffers 8 4k;
        proxy_busy_buffers_size 8k;
        
        # ヘッダー用の個別バッファ
        proxy_buffers_size 4k;
        
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

テスト環境: Ubuntu 22.04 LTS / Nginx 1.25.3 で動作確認済み

よくある質問

Q1: 複数のリバースプロキシサーバーを配置する場合、どのように構成すれば良いですか?

A: DNSラウンドロビンまたはロードバランサー(HAProxy、AWS ALBなど)の背後に複数のNginxインスタンスを配置するのが標準的です。バックエンドサーバー間の負荷分散はNginx側で、Nginxサー

K
AWS・Python・生成AIを専門とするソフトウェアエンジニア。AI・クラウド・開発ワークフローの実践ガイドを執筆しています。詳しく見る →