ブログ | NGINX

NGINX 設定のよくある 10 の間違いを避ける

NGINX-F5 水平黒タイプ RGB の一部
ティモ・スターク サムネイル
ティモ・スターク
2022年2月22日公開

問題を抱えている NGINX ユーザーを支援する際、他のユーザーの設定で何度も見てきたのと同じ設定ミスを頻繁に目にします。時には、他の NGINX エンジニアが書いた設定でも同様のミスが見られることがあります。 このブログでは、最も一般的なエラー 10 個を取り上げ、何が問題で、どのように修正するかを説明します。

  1. ワーカーあたりのファイル記述子が足りません
  2. error_logオフディレクティブ
  3. 上流サーバーへのキープアライブ接続を有効にしない
  4. ディレクティブ継承の仕組みを忘れる
  5. proxy_buffering offディレクティブ
  6. ifディレクティブの不適切な使用
  7. 過剰な健康診断
  8. メトリックへの安全でないアクセス
  9. すべてのトラフィックが同じ /24 CIDR ブロックから来る場合にip_hashを使用する
  10. 上流グループを活用しない

間違い1: ワーカーあたりのファイル記述子が足りません

worker_connectionsディレクティブは、NGINX ワーカー プロセスが開くことができる同時接続の最大数を設定します (デフォルトは 512)。 クライアント接続だけでなく、すべての種類の接続 (プロキシ サーバーとの接続など) が最大数にカウントされます。 ただし、ワーカーあたりの同時接続数には、最終的には別の制限があることに留意することが重要です。それは、各プロセスに割り当てられるファイル記述子 (FD) の最大数に対するオペレーティング システムの制限です。 最近の UNIX ディストリビューションでは、デフォルトの制限は 1024 です。

最も小規模な NGINX デプロイメントを除くすべての場合、ワーカーあたり 512 接続という制限はおそらく小さすぎます。 実際、NGINX オープンソースバイナリと NGINX Plus で配布されるデフォルトのnginx.confファイルでは、この値が 1024 に増加されます。

よくある設定ミスは、FD の制限を、 worker_connectionsの値の少なくとも 2 倍に増やさないことです。 修正方法は、メイン構成コンテキストのworker_rlimit_nofileディレクティブを使用してその値を設定することです。

より多くの FD が必要な理由は、NGINX ワーカー プロセスからクライアントまたはアップストリーム サーバーへの各接続で FD が消費されるためです。NGINX が Web サーバーとして機能する場合、クライアント接続に 1 つの FD を使用し、提供されるファイルごとに 1 つの FD を使用します。つまり、クライアントごとに最低 2 つの FD が使用されます (ただし、ほとんどの Web ページは多数のファイルから構築されます)。 プロキシ サーバーとして機能する場合、NGINX はクライアントとアップストリーム サーバーへの接続にそれぞれ 1 つの FD を使用し、サーバーの応答を一時的に保存するために使用されるファイル用に 3 番目の FD を使用する可能性があります。 キャッシュ サーバーとして、NGINX はキャッシュされた応答に対しては Web サーバーのように動作し、キャッシュが空または期限切れの場合はプロキシ サーバーのように動作します。

NGINX は、ログ ファイルごとに 1 つの FD を使用し、マスター プロセスと通信するためにいくつかの FD も使用しますが、通常、これらの数は接続やファイルに使用される FD の数と比較すると小さくなります。

UNIX では、プロセスあたりの FD の数を設定する方法がいくつか用意されています。

  • シェルからNGINXを起動する場合のulimitコマンド
  • NGINXをサービスとして起動する場合のinitスクリプトまたはsystemdサービスマニフェスト変数
  • /etc/security/limits.confファイル

ただし、使用する方法は NGINX の起動方法によって異なりますが、 worker_rlimit_nofile はNGINX の起動方法に関係なく機能します。

FD の数にはシステム全体の制限もあり、これは OS のsysctl fs.file-maxコマンドで設定できます。 通常は十分な大きさですが、すべての NGINX ワーカー プロセスが使用する可能性のあるファイル記述子の最大数 ( worker_rlimit_nofile * worker_processes ) がfs.file‑maxよりも大幅に少ないことを確認する価値があります。 NGINX が何らかの理由で利用可能なすべての FD を使用した場合 (たとえば、DoS 攻撃中)、問題を解決するためにマシンにログインすることさえ不可能になります。

間違い2: error_log offディレクティブ

よくある間違いは、 error_log offディレクティブがログ記録を無効にすると考えることです。 実際、 access_logディレクティブとは異なり、 error_log はoffパラメータを取りません。 設定にerror_log offディレクティブを含めると、NGINX は NGINX 設定ファイルのデフォルト ディレクトリ (通常は/etc/nginx ) にoffという名前のエラー ログ ファイルを作成します。

エラー ログは、NGINX の問題をデバッグする際に重要な情報源となるため、無効にすることはお勧めしません。ただし、ストレージが限られていて、使用可能なディスク領域を使い果たすほどのデータがログに記録される可能性がある場合は、エラー ログを無効にするのが合理的です。 メイン構成コンテキストに次のディレクティブを含めます。

error_log /dev/null が発生する;

このディレクティブは、NGINX が設定を読み取って検証するまで適用されないことに注意してください。 そのため、NGINX が起動するたび、または設定が再ロードされるたびに、設定が検証されるまで、デフォルトのエラー ログの場所 (通常は/var/log/nginx/error.log ) にログが記録される可能性があります。 ログ ディレクトリを変更するには、 nginxコマンドに-e < error_log_location >パラメータを含めます。

間違い3: 上流サーバーへのキープアライブ接続を有効にしない

デフォルトでは、NGINX は新しい受信リクエストごとにアップストリーム (バックエンド) サーバーへの新しい接続を開きます。 これは安全ですが非効率的です。NGINX とサーバーは接続を確立するために 3 つのパケットを交換し、接続を終了するために 3 つまたは 4 つのパケットを交換する必要があるためです。

トラフィック量が多い場合、リクエストごとに新しい接続を開くと、システム リソースが使い果たされ、接続をまったく開けなくなる可能性があります。 理由は次のとおりです。各接続について、送信元アドレス、送信元ポート、宛先アドレス、宛先ポートの4 つのタプルが一意である必要があります。 NGINX からアップストリーム サーバーへの接続の場合、要素のうち 3 つ (1 番目、3 番目、4 番目) は固定され、送信元ポートのみが変数として残ります。 接続が閉じられると、Linux ソケットは 2 分間TIME‑WAIT状態のままになります。これにより、トラフィック量が多い場合に、使用可能なソース ポートのプールが枯渇する可能性が高くなります。 そうなると、NGINX はアップストリーム サーバーへの新しい接続を開くことができなくなります。

修正方法は、NGINX とアップストリーム サーバー間のキープアライブ接続を有効にすることです。リクエストが完了したときに接続が閉じられるのではなく、接続は開いたままになり、追加のリクエストに使用されます。 これにより、ソース ポートが不足する可能性が減り、パフォーマンスが向上します

キープアライブ接続を有効にするには:

  • 各ワーカー プロセスのキャッシュに保存されるアップストリーム サーバーへのアイドル キープアライブ接続の数を設定するには、すべてのアップストリーム {}ブロックにkeepaliveディレクティブを含めます。

    注意: keepaliveディレクティブは、NGINX ワーカー プロセスが開くことができるアップストリーム サーバーへの接続の合計数を制限しません。これはよくある誤解です。 したがって、 keepaliveのパラメータは、思ったほど大きくする必要はありません。

    パラメータは、 upstream{}ブロックにリストされているサーバーの数の 2 倍に設定することをお勧めします。 これは、NGINX がすべてのサーバーとのキープアライブ接続を維持するのに十分な大きさですが、上流サーバーが新しい着信接続も処理できるほど小さいです。

    また、 upstream{}ブロックでhaship_hashleast_connleast_time 、またはrandomディレクティブを使用して負荷分散アルゴリズムを指定する場合、そのディレクティブはkeepaliveディレクティブの上に表示する必要があることにも注意してください。 これは、NGINX 構成内のディレクティブの順序は重要ではないという一般的なルールのまれな例外の 1 つです。

  • リクエストをアップストリーム グループに転送するlocation{}ブロックに、 proxy_passディレクティブとともに次のディレクティブを含めます。

    proxy_http_version 1.1;
    proxy_set_header "接続" "";
    

    デフォルトでは、NGINX はアップストリーム サーバーへの接続に HTTP/1.0 を使用し、それに応じてサーバーに転送するリクエストにConnection: closeヘッダーを追加します。 その結果、 upstream{}ブロックにkeepaliveディレクティブが存在するにもかかわらず、リクエストが完了すると各接続が閉じられます。

    proxy_http_versionディレクティブは、NGINX に代わりに HTTP/1.1 を使用するように指示し、 proxy_set_headerディレクティブはConnectionヘッダーからclose値を削除します。

間違い4: ディレクティブ継承の仕組みを忘れる

NGINX ディレクティブは下方向に、つまり「外側から内側へ」継承されます。つまり、コンテキスト (別のコンテキスト (その) 内にネストされているコンテキスト) は、親レベルに含まれるディレクティブの設定を継承します。 たとえば、 http{}コンテキスト内のすべてのserver{} ブロックlocation{}ブロックは、 httpレベルに含まれるディレクティブの値を継承し、 server{}ブロック内のディレクティブは、その中のすべての子location{}ブロックに継承されます。 ただし、親コンテキストとその子コンテキストの両方に同じディレクティブが含まれている場合、値は追加されず、代わりに子コンテキストの値が親の値を上書きします。

間違いは、配列ディレクティブのこの「オーバーライド ルール」を忘れることです。配列ディレクティブは、複数のコンテキストに含まれるだけでなく、特定のコンテキスト内で複数回含まれることもあります。 例としては、 proxy_set_headeradd_header などがあります。second の名前に「add」が含まれていると、オーバーライド ルールを忘れやすくなります。

add_headerのこの例で継承がどのように機能するかを説明します。

http { 
add_header X-HTTP-LEVEL-HEADER 1;
add_header X-ANOTHER-HTTP-LEVEL-HEADER 1;

server {
listen 8080;
location / {
return 200 "OK";
} 
}

server {
listen 8081;
add_header X-SERVER-LEVEL-HEADER 1;

location / {
return 200 "OK";
}

location /test {
add_header X-LOCATION-LEVEL-HEADER 1;
return 200 "OK";
}

location /correct {
add_header X-HTTP-LEVEL-HEADER 1;
add_header X-ANOTHER-HTTP-LEVEL-HEADER 1;

add_header X-SERVER-LEVEL-HEADER 1;
add_header X-LOCATION-LEVEL-HEADER 1;
200 "OK" を返します。
} 
}
}

ポート 8080 でリッスンしているサーバーの場合、 server{} ブロックにもlocation{}ブロックにもadd_headerディレクティブはありません。 したがって継承は簡単で、 http{}コンテキストで定義された 2 つのヘッダーが表示されます。

% curl -i localhost:8080 HTTP/1.1 200 OK サーバー: nginx/1.21.5 日付: 2022年2月21日(月)10:12:15 GMT コンテンツタイプ: text/plain コンテンツの長さ: 2 接続: キープアライブX-HTTP-LEVEL-HEADER: 1 X-別のHTTPレベルヘッダー: 1 OK

ポート 8081 でリッスンしているサーバーの場合、 server{}ブロックにはadd_headerディレクティブがありますが、その子location /ブロックには存在しません。 server{}ブロックで定義されたヘッダーは、 http{}コンテキストで定義された 2 つのヘッダーをオーバーライドします。

% curl -i localhost:8081 HTTP/1.1 200 OK サーバー: nginx/1.21.5 日付: 2022年2月21日(月)10:12:20 GMT コンテンツタイプ: text/plain コンテンツの長さ: 2 接続: キープアライブX-SERVER-LEVEL-HEADER: 1 OK

子の場所/testブロックにはadd_headerディレクティブがあり、親のserver{}ブロックのヘッダーとhttp{}コンテキストの 2 つのヘッダーの両方をオーバーライドします。

% curl -i localhost:8081/test HTTP/1.1 200 OK サーバー: nginx/1.21.5 日付: 2022年2月21日(月)10:12:25 GMT コンテンツタイプ: text/plain コンテンツの長さ: 2 接続: キープアライブX-LOCATION-LEVEL-HEADER: 1 OK

location{}ブロックで、親コンテキストで定義されたヘッダーとローカルで定義されたヘッダーを保持する場合は、 location{}ブロック内で親ヘッダーを再定義する必要があります。 location /correctブロックで行ったことは次の通りです:

% curl -i localhost:8081/correct HTTP/1.1 200 OK サーバー: nginx/1.21.5 日付: 2022年2月21日(月)10:12:30 GMT コンテンツタイプ: text/plain コンテンツの長さ: 2 接続: キープアライブX-HTTP-LEVEL-HEADER: 1 X-別のHTTPレベルヘッダー: 1 X-SERVERレベルヘッダー: 1 X-ロケーションレベルヘッダー: 1 OK

間違い5: proxy_buffering offディレクティブ

NGINX では、プロキシ バッファリングはデフォルトで有効になっています ( proxy_bufferingディレクティブがonに設定されています)。 プロキシ バッファリングとは、NGINX がサーバーからの応答を受信するとそれを内部バッファに保存し、応答全体がバッファリングされるまでクライアントへのデータの送信を開始しないことを意味します。 バッファリングは、低速クライアントでのパフォーマンスの最適化に役立ちます。NGINX は、クライアントが応答をすべて取得するのにかかる時間だけ応答をバッファリングするため、プロキシされたサーバーは、できるだけ早く応答を返すことができ、他の要求を処理できる状態に戻ることができます。

プロキシ バッファリングが無効になっている場合、NGINX は、クライアントへの送信を開始する前に、サーバーの応答の最初の部分のみを、デフォルトで 1 つのメモリ ページ(オペレーティング システムに応じて 4 KBまたは 8 KB ) のバッファにバッファリングします。 これは通常、応答ヘッダーにちょうど十分なスペースです。 NGINX は、応答を受信するとすぐにクライアントに応答を同期的に送信し、NGINX が次の応答セグメントを受け入れるまでサーバーをアイドル状態に待機させます。

そのため、設定でproxy_buffering がオフになっているのを頻繁に目にすることに驚きます。 おそらく、クライアントが経験する遅延を減らすことが目的ですが、その効果はごくわずかで、副作用は多数あります。プロキシ バッファリングが無効になっていると、レート制限とキャッシュが設定されていても機能せず、パフォーマンスが低下するなどです。

プロキシ バッファリングを無効にすることが意味をなすユースケースはごくわずかです (ロング ポーリングなど)。そのため、デフォルトを変更することは強くお勧めしません。 詳細については、 NGINX Plus 管理者ガイドを参照してください。

間違い6: ifディレクティブの不適切な使用

ifディレクティブは、特にlocation{}ブロックでは使用が難しいです。 期待どおりに動作しないことが多く、セグメント違反が発生することもあります。 実際、これは非常に厄介な問題なので、NGINX Wiki に「If is Evil」というタイトルの記事があり、問題とその回避方法の詳細な説明については、その記事を参照してください。

一般に、 if{}ブロック内で常に安全に使用できるディレクティブはreturnrewriteだけです。 次の例では、 if を使用して、 X‑Testヘッダーを含むリクエストを検出します (ただし、これはテストする任意の条件にすることができます)。 NGINXが復活 430 (リクエスト ヘッダ フィールド あまりにも 大きい) エラーが発生した場合、指定された場所でそれを傍受します 翻訳: そして、リクエストを上流のグループにプロキシします。 b

場所 / { 
error_page 430 = @error_430;
if ($http_x_test) {
return 430; 
}

proxy_pass http://a;
}

場所 @error_430 {
proxy_pass b;
}

この場合やifの他の多くの用途では、ディレクティブを完全に回避できる場合がよくあります。 次の例では、リクエストにX‑Testヘッダーが含まれている場合、 map{}ブロックは$upstream_name変数をbに設定し、リクエストはその名前のアップストリーム グループにプロキシされます。

$http_x_test $upstream_name をマップします { 
デフォルト "b";
"" "a";
}

# ...

場所 / {
proxy_pass http://$upstream_name;
}

間違い7: 過剰な健康診断

複数の仮想サーバーを構成して、同じアップストリーム グループへのリクエストをプロキシする (つまり、複数のserver{}ブロックに同一のproxy_passディレクティブを含める) ことは非常に一般的です。 この状況での間違いは、すべてのserver{}ブロックにhealth_checkディレクティブを含めることです。 これにより、追加の情報は得られず、アップストリーム サーバーにさらに負荷がかかるだけです。

明らかなリスクを冒して修正するには、 upstream{}ブロックごとにヘルスチェックを 1 つだけ定義します。 ここでは、適切なタイムアウトとヘッダー設定を備えた、特別な名前の付いた場所で、 bという名前のアップストリーム グループのヘルス チェックを定義します。

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

location @health_check {
health_check;
proxy_connect_timeout 2s;
proxy_read_timeout 3s;
proxy_set_header Host example.com;
proxy_pass http://b;
}

複雑な構成では、この例のように、 NGINX Plus APIおよびダッシュボードとともに、すべてのヘルスチェックの場所を単一の仮想サーバーにグループ化することで、管理をさらに簡素化できます。

server { 
listen 8080;

location / {
# …
}

location @health_check_b {
health_check;
proxy_connect_timeout 2s;
proxy_read_timeout 3s;
proxy_set_header Host example.com;
proxy_pass http://b;
}

location @health_check_c {
health_check;
proxy_connect_timeout 2s;
proxy_read_timeout 3s;
proxy_set_header Host api.example.com;
proxy_pass http://c;
}

location /api {
api write=on;
# API へのアクセスを制限するディレクティブ (以下の「間違い 8」を参照)
}

location = /dashboard.html {
root /usr/share/nginx/html;
}
}

HTTP、TCP、UDP、gRPC サーバーのヘルスチェックの詳細については、 NGINX Plus 管理者ガイドを参照してください。

間違い8: メトリックへの安全でないアクセス

NGINX 操作に関する基本的なメトリックは、 Stub Statusモジュールから入手できます。 NGINX Plus では、 NGINX Plus APIを使用して、より広範なメトリック セットを収集することもできます。メトリックの収集を有効にするには、それぞれserver{}またはlocation{}ブロックにstub_statusまたはapiディレクティブを含めます。これが、メトリックを表示するためにアクセスする URL になります。 ( NGINX Plus APIの場合、メトリックを収集する NGINX エンティティ(仮想サーバー、アップストリーム グループ、キャッシュなど)の共有メモリ ゾーンも構成する必要があります。NGINX Plus 管理者ガイドの手順を参照してください。)

一部のメトリックは、Web サイトや NGINX によってプロキシされるアプリを攻撃するために使用される可能性のある機密情報であり、ユーザー構成で時々見られる間違いは、対応する URL へのアクセスを制限していないことです。 ここでは、メトリックを保護する方法のいくつかを見ていきます。 最初の例ではstub_status を使用します。

次の設定では、インターネット上の誰でもhttp://example.com/basic_statusのメトリックにアクセスできるようになります。

サーバー { 
listen 80;
server_name example.com;

location = /basic_status {
stub_status;
}
}

HTTP 基本認証でメトリックを保護する

HTTP 基本認証を使用してメトリックをパスワードで保護するには、 auth_basicおよびauth_basic_user_fileディレクティブを含めます。 ファイル (ここでは.htpasswd ) には、メトリックを表示するためにログインできるクライアントのユーザー名とパスワードがリストされます。

server { 
listen 80;
server_name example.com;

location = /basic_status {
auth_basic “closed site”;
auth_basic_user_file conf.d/.htpasswd;
stub_status;
}
}

許可および拒否ディレクティブを使用してメトリックを保護する

承認されたユーザーにログインを要求せず、そのユーザーがメトリックにアクセスする IP アドレスがわかっている場合は、 allowディレクティブを使用することもできます。 個別の IPv4 および IPv6 アドレスと CIDR 範囲を指定できます。 deny allディレクティブは、他のすべてのアドレスからのアクセスを防止します。

server { 
listen 80;
server_name example.com;

location = /basic_status {
allow 192.168.1.0/24;
allow 10.1.1.0/16;
allow 2001:0db8::/32;
allow 96.1.2.23/32;
deny all;
stub_status;
}
}

2つの方法を組み合わせる

両方の方法を組み合わせたい場合はどうすればよいでしょうか? 特定のアドレスからのクライアントがパスワードなしでメトリックにアクセスできるようにし、異なるアドレスからのクライアントにはログインを要求することができます。 このために、 satisfy anyディレクティブを使用します。 これは、HTTP 基本認証資格情報を使用してログインするか、事前に承認された IP アドレスを使用しているクライアントにアクセスを許可するように NGINX に指示します。 セキュリティを強化するために、特定のアドレスからアクセスしたユーザーにもログインを要求するように「satisfied to all」を設定できます。

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

location = /basic_status {
いずれかを満たす;

auth_basic “closed site”;
auth_basic_user_file conf.d/.htpasswd;
allow 192.168.1.0/24;
allow 10.1.1.0/16;
allow 2001:0db8::/32;
allow 96.1.2.23/32;
deny all;
stub_status;
}
}

NGINX Plus では、同じ手法を使用して、 NGINX Plus APIエンドポイント (次の例ではhttp://monitor.example.com:8080/api/ ) と、 http://monitor.example.com/dashboard.htmlにあるライブ アクティビティ監視ダッシュボードへのアクセスを制限します。

この構成では、96.1.2.23/32 ネットワークまたはローカルホストからのクライアントのみにパスワードなしのアクセスを許可します。 ディレクティブはサーバーレベルで定義されるため、API とダッシュボードの両方に同じ制限が適用されます。 補足として、 apiへのwrite=onパラメータは、これらのクライアントが API を使用して構成を変更できることも意味します。

API とダッシュボードの設定の詳細については、 NGINX Plus 管理者ガイドを参照してください。

server { 
listen 8080;
server_name monitor.example.com;

いずれかを満たす;
auth_basic “closed site”;
auth_basic_user_file conf.d/.htpasswd;
allow 127.0.0.1/32;
allow 96.1.2.23/32;
deny all;

location = /api/ { 
api write=on;
}

location = /dashboard.html {
root /usr/share/nginx/html;
}
}

間違い9: すべてのトラフィックが同じ /24 CIDR ブロックから来る場合にip_hashを使用する

ip_hashアルゴリズムは、クライアント IP アドレスのハッシュに基づいて、 upstream{}ブロック内のサーバー間でトラフィックの負荷を分散します。 ハッシュ キーは、IPv4 アドレスの最初の 3 オクテットまたは IPv6 アドレス全体です。 このメソッドはセッションの永続性を確立します。つまり、サーバーが利用できない場合を除いて、クライアントからの要求は常に同じサーバーに渡されます。

高可用性を実現するように構成された仮想プライベート ネットワークに、NGINX をリバース プロキシとして導入したとします。 さまざまなファイアウォール、ルーター、レイヤー 4 ロード バランサー、ゲートウェイを NGINX の前に配置して、さまざまなソース (内部ネットワーク、パートナー ネットワーク、インターネットなど) からのトラフィックを受け入れ、それを NGINX に渡して上流サーバーにリバース プロキシします。 NGINX の初期設定は次のとおりです。

http {
アップストリーム {
ip_hash;
サーバー 10.10.20.105:8080;
サーバー 10.10.20.106:8080;
サーバー 10.10.20.108:8080;
}

サーバー {# …}
}

しかし、問題があることが判明しました。すべての「傍受」デバイスが同じ 10.10.0.0/24 ネットワーク上にあるため、NGINX にとっては、すべてのトラフィックがその CIDR 範囲内のアドレスから送信されているように見えます。 ip_hashアルゴリズムは IPv4 アドレスの最初の 3 オクテットをハッシュすることを覚えておいてください。 私たちの展開では、最初の 3 つのオクテットはすべてのクライアントで同じ (10.10.0) なので、ハッシュはすべてのクライアントで同じであり、トラフィックを異なるサーバーに分散する根拠はありません。

修正方法は、ハッシュ キーとして$binary_remote_addr変数を使用して、代わりにハッシュアルゴリズムを使用することです。 この変数は完全なクライアント アドレスをキャプチャし、それを IPv4 アドレスの場合は4 バイト、IPv6 アドレスの場合は 16 バイトのバイナリ表現に変換します。 これで、ハッシュは傍受デバイスごとに異なり、負荷分散は期待どおりに機能します。

また、デフォルトの代わりにketamaハッシュ メソッドを使用するための、 consistentパラメーターも含めます。 これにより、サーバーのセットが変更されたときに別のアップストリーム サーバーに再マップされるキーの数が大幅に削減され、キャッシュ サーバーのキャッシュ ヒット率が高くなります。

http { 
アップストリーム {
ハッシュ $binary_remote_addr が一致しています。
サーバー 10.10.20.105:8080。
サーバー 10.10.20.106:8080。
サーバー 10.10.20.108:8080。
}

サーバー {# …}
}

間違い10: 上流グループを活用しない

最も単純なユースケースの 1 つとして、ポート 3000 でリッスンする単一の NodeJS ベースのバックエンド アプリケーションのリバース プロキシとして NGINX を使用するとします。 一般的な構成は次のようになります。

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

location / {
proxy_set_header Host $host;
proxy_pass http://localhost:3000/;
}
}
}

簡単ですよね? proxy_passディレクティブは、クライアントからのリクエストを送信する場所を NGINX に指示します。 NGINX が行う必要があるのは、ホスト名を IPv4 または IPv6 アドレスに解決することだけです。 接続が確立されると、NGINX はそのサーバーにリクエストを転送します。

ここでの間違いは、サーバーが 1 台しかないため、負荷分散を構成する理由がなく、 upstream{}ブロックを作成しても意味がないと想定することです。 実際、 upstream{}ブロックは、次の構成に示すように、パフォーマンスを向上させるいくつかの機能を有効にします。

http {
アップストリーム node_backend {
ゾーン アップストリーム 64K;
サーバー 127.0.0.1:3000 max_fails=1 fail_timeout=2s;
キープアライブ 2;
}

サーバー {
listen 80;
サーバー名 example.com;

場所 / {
proxy_set_header Host $host;
proxy_pass http://node_backend/;
proxy_next_upstream error timeout http_500;

}
}
}

ゾーンディレクティブは、ホスト上のすべての NGINX ワーカー プロセスがアップストリーム サーバーの構成と状態情報にアクセスできる共有メモリ ゾーンを確立します。 複数のアップストリーム グループがゾーンを共有できます。 NGINX Plus を使用すると、ゾーンでは、 NGINX Plus API を使用して、NGINX を再起動せずにアップストリーム グループ内のサーバーと個々のサーバーの設定を変更することもできます。詳細については、 NGINX Plus 管理者ガイドを参照してください。

サーバーディレクティブには、サーバーの動作を調整するために使用できるいくつかのパラメーターがあります。 この例では、サーバーが正常でないためリクエストを受け入れることができないと判断するために NGINX が使用する条件を変更しました。 ここでは、通信試行が2 秒ごとに 1 回でも失敗すると (デフォルトでは10 秒ごとに 1 回)、サーバーが正常でないとみなされます。

この設定をproxy_next_upstreamディレクティブと組み合わせて、NGINX が失敗した通信試行と見なすものを構成します。この場合、NGINX はリクエストをアップストリーム グループ内の次のサーバーに渡します。 デフォルトのエラーとタイムアウト条件にhttp_500を追加して、NGINXがHTTPと見なすようにします。 500(内部サーバーエラー)失敗した試行を表す上流サーバーからのコード。

keepaliveディレクティブは、各ワーカー プロセスのキャッシュに保存されるアップストリーム サーバーへのアイドル キープアライブ接続の数を設定します。 間違い 3 の利点についてはすでに説明しました。 アップストリーム サーバーへのキープアライブ接続を有効にしません

NGINX Plus を使用すると、アップストリーム グループで追加機能を設定できます。

  • 上で述べたように、NGINX Open Source は起動時に 1 回だけサーバーのホスト名を IP アドレスに解決します。 server ディレクティブのresolveパラメータにより、NGINX Plus はアップストリーム サーバーのドメイン名に対応する IP アドレスの変更を監視し、再起動せずにアップストリーム構成を自動的に変更できるようになります。

    さらに、サービスパラメータにより、NGINX Plus はポート番号、重み、優先度に関する情報を含む DNS SRVレコードを使用できるようになります。 これは、サービスのポート番号が動的に割り当てられることが多いマイクロサービス環境では重要です。

    サーバー アドレスの解決の詳細については、ブログの「NGINX および NGINX Plus でのサービス検出に DNS を使用する」を参照してください。

  • server ディレクティブのslow_startパラメータにより、NGINX Plus は、新たに正常であると判断され、リクエストを受け入れることができるようになったサーバーに送信するリクエストの量を徐々に増やすことができます。 これにより、突然の大量のリクエストによってサーバーが過負荷になり、再度障害が発生するのを防ぐことができます。

  • キューディレクティブを使用すると、リクエストを処理するアップストリーム サーバーを選択できない場合に、NGINX Plus はクライアントにすぐにエラーを返すのではなく、リクエストをキューに配置できるようになります。

リソース

NGINX Plus をお試しいただくには、今すぐ30 日間の無料トライアルを開始するか、弊社にお問い合わせの上、使用事例についてご相談ください


「このブログ投稿には、入手できなくなった製品やサポートされなくなった製品が参照されている場合があります。 利用可能な F5 NGINX 製品およびソリューションに関する最新情報については、 NGINX 製品ファミリーをご覧ください。 NGINX は現在 F5 の一部です。 以前の NGINX.com リンクはすべて、F5.com の同様の NGINX コンテンツにリダイレクトされます。"