はじめに
nginx の利用用途として多いリバースプロキシの設定まとめです。
nginx の導入方法については以下を参照してください。
/etc/nginx/conf.d/default.conf;
に対する設定(http
コンテキスト配下)として記載します。
upstream コンテキストによるバックエンドの指定
リバースプロキシとして扱うには upstream
コンテキストでバックエンドのサーバを指定します。
upstream backend1 { server 192.168.0.1:8080; server 192.168.0.2:8080; } server { listen 80; server_name localhost; location / { proxy_pass http://backend1; } }
ここでは backend1
という名前でバックエンドサーバのグループに名前を付けています。
nginx で受け付けたリクエストがバックエンドのサーバ 192.168.0.1 と 192.168.0.2 に転送されます。
location
コンテキスト内の proxy_pass
ディレクティブで backend1
という名前で転送先を指定します。
バックエンドへのリクエストを http://backend1
のように upstream の名前とした場合、リクエストパスがそのままバックエンドにリクエストされます。
http://backend1/foo/
のように upstream の名前の後にパス名をつけた場合、location で指定したパス名が置換されます。
以下のような設定があった場合
location /path { proxy_pass http://backend1/foo/; }
/pathbar/index.html
というパスでのリクエストは /foo/bar/index.html
というパスでバックエンドにリクエストされます。
proxy_pass
により書き換えられたリクエストは、バックエンドサーバからリダイレクトされた場合でも Location ヘッダが適切な値に書き換えられます。
これは proxy_redirect
ディレクティブのデフォルト値が default
と定義されているためです。
rewrite
ディレクティブなどによりURLの書き換えを行った場合には、proxy_redirect
ディレクティブで書き換えルールを指定することができます。
リバースプロキシ側で HTTPS 通信を行い、バックエンドには HTTP 接続を行うには、通常通り nginx 側に SSL の設定を行うことで対応できます。
server { listen 443 ssl; ssl_certificate /path/to/certificate; ssl_certificate_key /path/to/certificate_key; }
リクエストのバランシング
先程の例では、バックエンドへのリクエストの振り分けはラウンドロビンで行われます。
振り分けに重み付けを行うには以下のように weight
を指定することができます。
upstream backend1 { server 192.168.0.1:8080 weight=2; server 192.168.0.2:8080; }
weight
を省略した場合には weight=1
と同等となり、192.168.0.1 に 66%、192.168.0.2 に 33% のリクエストがわりふられます。
一方を待機系にするには backup
を指定します。
upstream backend1 { server 192.168.0.1:8080; server 192.168.0.2:8080 backup; }
通常系にエラーが発生した場合に限り、待機系にリクエストするようになります。
接続数の少ないバックエンドに優先的に振り分けを行うには以下のように least_conn
を指定します。
upstream backend1 { least_conn; server 192.168.0.1:8080; server 192.168.0.2:8080; }
接続元のIPアドレスに応じて振り分け先を固定するには ip_hash
を指定します。
upstream backend1 { ip_hash; server 192.168.0.1:8080; server 192.168.0.2:8080; }
クライアントIPアドレスのハッシュ値に応じて振り分け先が決定されます。
クライアントのIPアドレスではなく、任意の値のハッシュ値により振り分けを行うには以下のようにします。
upstream backend1 { hash $http_user_agent; server 192.168.0.1:8080; server 192.168.0.2:8080; }
この例ではユーザエージェントのハッシュ値による振り分けを行います。
タイムアウト
バックエンドサーバに対するタイムアウトは以下のように指定します。
location / { proxy_pass http://backend1; proxy_connect_timeout 60s; proxy_read_timeout 60s; proxy_send_timeout 60s; }
proxy_connect_timeout
は接続タイムアウトとなります。TCP接続が開始できない場合はすぐに別サーバへ振り分けが行われますが、接続シーケンスのやり取りの応答が得られない場合などはここで設定したタイムアウトで処理が打ち切られて別サーバへの振り分けが行われます。
proxy_read_timeout
と proxy_send_timeout
はそれぞれ受信/送信データが残っているが、それらの受信/送信処理が滞った場合のタイムアウトです。
タイムアウトが発生した場合、同じリクエストを振り分け先のサーバに対してリトライします。そのため短すぎるタイムアウトを設定した場合多重POSTなどが発生するケースがあるため注意が必要です。
タイムアウトが発生した場合、対象サーバへのアクセスはデフォルトで10秒間抑止されます。これらの動作を変更する場合には、max_fails
と fail_timeout
を使います。
upstream backend1 { server 192.168.0.1:8080 max_fails=2 fail_timeout=15s; server 192.168.0.2:8080; }
上記の設定とした場合、15秒以内に2回バックエンドサーバへのアクセスが失敗した場合、15秒間は対象サーバへのアクセスを控える動作となります。
リクエストヘッダの追加
クライアントのIPアドレスなどはリバースプロキシ側で X-
で始まる追加ヘッダとして付与することが一般的です。
proxy_set_header
を使うことでバックエンドのサーバに追加のヘッダ情報を引き渡すことができます。
server { proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Server $hostname; proxy_set_header X-Real-IP $remote_addr; }
バックエンドへの Keep-Alive 接続
nginx ではバックエンドへのリクエストは HTTP/1.0 となり Connection は close
となります。
バックエンドへのリクエストに Keep-Alive を使うには以下のようにします。
upstream backend1 { server 192.168.0.1:8080; server 192.168.0.2:8080; keepalive 32 } server { listen 80; location / { proxy_set_header Connection ""; proxy_http_version 1.1; proxy_pass http://app1; } }
server.location
コンテキストで proxy_set_header Connection
でヘッダを空に設定し、proxy_http_version
で HTTP/1.1 を利用するように設定します。
upstream
コンテキストの keepalive
ディレクティブでは、Keep-Alive で接続を保持する待機中のコネクション数(worker別)を指定します。
- 作者:Dimitri Aivaliotis
- 発売日: 2013/10/26
- メディア: 大型本
nginx実践ガイド impress top gearシリーズ
- 作者:渡辺高志
- 発売日: 2017/02/16
- メディア: Kindle版