...

リバースプロキシとして最高のパフォーマンスを引き出すためのNGINXアップストリーム・キープアライブの最適な設定

NGINXのアップストリーム・キープアライブを設定し、リバースプロキシが確立する接続数を減らし、遅延を低減させ、負荷のピークを確実に吸収できるようにします。その際、以下の設定を行います。 プールの大きさ, タイムリミットやヘッダーを適切に設定し、接続の再利用を図り、データパスをスリムに保つようにします。.

中心点

  • HTTP/1.1 強制実行およびConnectionヘッダーのクリーンアップ
  • keepalive 作業員1人あたりに適切な規模を設定する
  • タイムアウト バックエンドの値に合わせて調整する
  • リクエスト/接続 削減とリサイクル
  • モニタリング 接続速度と遅延について

Upstream Keepaliveが接続のオーバーヘッドを劇的に削減する理由

再利用を行わない場合、NGINXはリクエストごとに新しいバックエンド接続を開くことになり、余分なハンドシェイクやCPUサイクルの増加、さらにはカーネルリソースの追加消費を招きます。まさにここで キープアライブ 。NGINXには、すでに確立され、現在アイドル状態にあるソケットをキャッシュさせ、後続のリクエストに再利用させるようにしています。これにより、接続時間が目に見えて短縮されます。その結果、1秒あたりの接続数が減少し、バックログのピークが緩和され、OSにおけるコンテキスト切り替えの負荷も軽減されます。 特にバックエンドへのTLS通信では、セッションの再利用によって顕著な時間短縮が実現します。これにより、スループットが高い場合でもレスポンスチェーンが安定します。 信頼できる そして、スムーズに応答する。.

基本原則とアップストリームにおけるkeepaliveディレクティブ

指令 keepalive upstreamブロックでは、ワーカーごとにキャッシュされるアイドル状態のバックエンド接続数を制限しています。この制限はグローバルに適用されるのではなく、厳密に各ワーカープロセスごとに適用されるため、私は常にワーカーの数を注視しています。 プールが満杯になると、NGINXは新しいソケットのためのスペースを確保するために、最も長く未使用の状態にある接続から順に閉じます。 再利用を行うには、プロキシ側でHTTP/1.1と、中立化されたConnectionヘッダーが必要です。これらの要件が満たされない場合、アップストリームで「keepalive」を設定していてもプールは空のままとなります。これは多くの管理者にとって 当初 驚いた。.

upstream backend_pool {
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
    server 192.168.1.12:8080;

    keepalive 32; # ワーカーごとのアイドル接続数
    keepalive_requests 1000;   # N回のリクエスト後のリサイクル
    keepalive_timeout 60s;     # アイドル時の有効期間
}

server {
    listen 80;
    location / {
 proxy_pass http://backend_pool;
 proxy_http_version 1.1;
 proxy_set_header Connection "";
    }
}

Locationブロックにおける必須のディレクティブ:HTTP/1.1とヘッダー制御

プロキシパスでは、HTTP/1.0 では Keepalive が正常に機能せず、接続が不必要に切断されてしまうため、NGINX に HTTP/1.1 を強制しています。このディレクティブ プロキシ したがって、1.1 は必須となります。さらに、バックエンドに「close」命令が届かないよう、通常のリクエストについては Connection ヘッダーを削除しています。 WebSockets などのアップグレードについては、通常の再利用に影響を与えないよう、map を使用して意図的に「Connection: Upgrade」を設定しています。これにより、接続ポリシーの一貫性が保たれ、クライアントヘッダーから切り離されます。まさにこの小さな変更が、多くの特定しにくい問題を未然に防いでいます。 エラーパターン.

location / {
    proxy_pass http://backend_pool;
    proxy_http_version 1.1;
    proxy_set_header Connection "";
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
}

map $http_upgrade $connection_upgrade {
    default upgrade;
    "" "";
}

微調整:keepalive_requests と keepalive_timeout を適切に設定する

2つの調整ネジを使って、接続の寿命と更新を制御し、プールが常に新鮮な状態を保ち、放置されたソケットが邪魔にならないようにしています。具体的には、 keepalive_requests および keepalive_timeout。N回のリクエスト後、NGINXは意図的に接続を切断し、必要に応じて再確立するため、ネットワークの経年劣化による影響を緩和します。アイドルタイムアウトは、バックエンドがそれ以前に接続を切断しないよう、30秒から120秒の間で、やや短めに設定しています。 重要なのは調整です。NGINXの設定値は、アプリサーバーのタイムアウト値を決して上回らないようにしてください。そうしないと、接続のリセットが頻発してしまいます。背景についてさらに詳しく知りたい方は、以下の記事で実践的なヒントをご覧いただけます。 キープアライブ・タイムアウト, 、典型的な値や相互作用について解説している。.

一目で把握できるよう、一般的な初期値とその用途を分かりやすくまとめた テーブル. 。これらの目安は出発点として機能し、モニタリングの結果、実際にはこれより若干高くなったり低くなったりすることがよくあります。 期間が短すぎると不必要な再構築が発生し、長すぎると古い接続が維持されてしまいます。接続あたりのリクエスト数については、プールを空にすることなく、異常値の影響を防ぐようにしています。これらの基本データを用いることで、非常に迅速に機能する デフォルト.

パラメータ 目的 基準値 チューニングに関する注意事項
keepalive ワーカーごとのアイドルプールのサイズ 32-64 ワーカーごとの同時負荷に合わせて調整する
keepalive_requests 接続あたりの最大リクエスト数 500–1000 長時間の配信の場合は、少し高めに設定する
keepalive_timeout 接続ごとの最大アイドル時間 60年代 バックエンドのアイドルタイムアウトを短縮するか、そのままにするか

同時接続数に基づいてプールのサイズを決定する

プールのサイズは、1秒あたりのリクエスト数ではなく、 コンカレンシー ワーカーあたり。まず、バックエンドへの並列リクエストの平均数と最大数を算出します。次に、これらの数値をNGINXワーカーの数で割り、切り上げます。 4つのワーカーで200件の同時リクエストの場合、ワーカーあたり約50件となるため、初期値としてkeepalive 64が適切です。これにより、不必要に多くのソケットを開いたままにすることなく、ソケットの利用可能性を維持できます。 コネクション を縛る。.

新しいバージョンのNGINXの特長を意図的に活用する

最新のバージョンでは、デフォルトで再利用が許可されていることが多いですが、制限は比較的厳しめになっています。それでも、私はそれらの値を入力しています 明示的に 。これにより再現性が確保され、チューニングが容易になり、アップデート後の予期せぬ事態を防ぐことができます。パラメータ「local」を使用すれば、セキュリティプロファイルやヘッダーポリシーが異なる場合、再利用の範囲を特定のロケーションに限定することも可能です。これにより、再利用のメリットをグローバルなレベルで損なうことなく、分離を明確に保つことができます。 明確な値を設定することで、意図を文書化し、後々の手間を省くことができます。 分析時間.

モニタリングと指標:設定は本当に効果を発揮しているのか?

まず、1秒あたりの新規バックエンド接続数を確認します。著しい減少が見られれば、対策が効果を上げていることになります。 再利用. 次に、upstream_connect_time を観察します。これは、プール内でヒットした場合、ほぼゼロになります。ログ上のエラー、特に接続リセットは、バックエンドの値よりも短いタイムリミットを示唆しています。 さらに、バックエンドのCPU使用率やレイテンシと、再利用された接続の割合との相関関係を分析しています。より深い理解を得るために、 接続の再利用 さまざまな負荷パターンにおける影響を示す例が参考になります。.

よくある原因を素早く解消する

バックエンドへのHTTP/1.1が欠けていると、どれほど高く設定しても、接続は短命のままです。 keepalive 設定します。クライアントが「Connection: close」を送信し、そのヘッダーをフィルタリングせずに通過させると、バックエンドは応答の直後にすべての接続を解放してしまいます。アイドルタイムアウトが一致しない場合、アプリ側が先に接続を終了し、NGINXは次のリクエストでリセットを受けてしまいます。 プールサイズが大きすぎると、開いたままのソケットが多くなり、メモリとポートを無駄に消費してしまいます。私は分析のたびに、以下の4つの点を確認しています。 第一に, 、というのも、それらがあらゆる問題の90 %を説明しているからだ。.

実例:高スループット向けのリファレンス構成

わずかな指示で、負荷のかかっているプロキシを高速かつ信頼性の高い状態に整え、ヘッダーの正確な転送を確保します。以下の方法は実績があり、簡単に カスタマイズ. 。keepaliveを64に設定し、接続あたりのリクエスト数を1000に制限し、アイドル時間を60秒に設定しています。さらに、バックエンドがロジックやレート制限を適用できるよう、ホストおよび転送情報を正しく転送しています。 この組み合わせにより、CPUへの負荷を軽減し、応答時間を短縮し、負荷のピークにもより余裕を持って対応できます。まさにこの方法で、予測しやすい パフォーマンス.

upstream app_backend {
    server 10.0.1.10:3000 max_fails=2 fail_timeout=30s;
    server 10.0.1.11:3000 max_fails=2 fail_timeout=30s;

    keepalive 64;
    keepalive_requests 1000;
    keepalive_timeout 60s;
}

server {
    listen 80;
    server_name example.com;

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

ホスティング環境と、本当に重要な運用上の側面

私はよく、PHP-FPM、Node.js、あるいはJavaサービスの前にNGINXを配置し、ネットワークの遅延を最小限に抑え、バックエンドのタイムアウトが一定になるよう注意を払っています。これにより、 計画性. 適切なソケット制限を設定した堅牢なカーネルネットワーク構成により、多数のオープン接続による競合を防ぎます。CPUのリソースを均等に割り当て、ストレージへのアクセス経路を高速化することで、バックエンドが短い応答時間を維持できるよう支援します。さらに、変更履歴を追跡できるように、バージョン管理された設定を徹底しています。 こうした徹底した管理により、トラフィックのピーク時でもシステムは安定した状態を保ちます。 反応性のある.

継続運営のためのベストプラクティス

まず、keepaliveを32~64、接続あたりのリクエスト数を500~1000、アイドル時間を60秒に設定して開始し、その後、体系的に測定を行いながら値を調整します。そうすることで、迅速な 成功. 変更を行う際は、接続率、レイテンシ、エラーパターンに関するメトリクスを常に監視し、グラフの変動が落ち着くまで追跡します。プールのサイズは、1秒あたりの生スループットではなく、同時リクエスト数に基づいて調整します。 タイムアウトは、バックエンドスタック側の設定よりも長く設定しないようにしてください。そうしないと、散発的なリセットが発生する恐れがあります。さらに細かく調整したい場合は、微調整に関するヒントを以下で確認できます。 キープアライブ要求の最適化, これによりリサイクルが容易になります。.

プロキシのタイムアウトとTCPキープアライブの調整

純粋なキープアライブパラメータに加え、トランスポートのタイムリミットも精密に調整しています。以下の3つの要素からなる プロキシ接続タイムアウト, proxy_send_timeout そして proxy_read_timeout NGINXが接続の確立、送信、受信においてどの程度忍耐強く動作するかを決定します。私はこれらの値を、バックエンド側の対応する値よりも高く設定することは決してなく、エラーを早期に検知し、アプリ側で問題が深刻化しないよう、わずかに低い値に設定しています。さらに、以下を有効にしています。 proxy_socket_keepalive, 、これにより、OSが一定間隔で非アクティブなソケットに対して「生存確認」を送信し、半開きの接続を検知できるようになります。これにより、プール内に死んだ接続が残り続け、次のリクエスト時にレイテンシの急上昇を引き起こすのを防ぎます。.

server {
    listen 80;

    location / {
 proxy_pass http://backend_pool;

 proxy_connect_timeout 3s;   接続できない場合は速やかにタイムアウト(#)
 proxy_send_timeout    30s;  # バックエンドへの書き込み
 proxy_read_timeout    30s;  # バックエンドからの応答
 proxy_socket_keepalive on;  # OSのTCPキープアライブを有効化
    }
}

長期にわたるストリーム(SSE や WebSockets など)については、接続は維持したまま、read のタイムアウトのみを延長しています。これにより、不具合のあるターゲットには迅速に対応しつつ、正当な長時間の応答については妨げることなく処理させることができます。.

リソース計画:worker_connections、FD、および一時ポート

ファイルディスクリプタの制限やポート範囲が枯渇してしまうと、クリーンなキープアライブ・プールも意味をなさなくなります。そのため、私は次のように計画しています。 ワーカーコネクション そして worker_rlimit_nofile 余裕を見て計算します。大まかな計算としては、ワーカー1人あたりの未処理FD数 ≈ (同時クライアント接続数 + 同時バックエンド接続数 + プールされたアイドルソケット数)となります。プールを用いた複数のアップストリームを設定すると、必要な数は倍増します。 また、NGINXはバックエンド側に対してTCPクライアントとして動作し、TIME_WAIT状態を蓄積するため、システムのエフェメラルポート範囲にも注意を払っています。.

worker_processes auto;
worker_rlimit_nofile 131072;

events {
    worker_connections 8192;
}
# Linux の例(sysctl):
net.core.somaxconn = 4096
net.ipv4.ip_local_port_range = 10240 65535
net.ipv4.tcp_fin_timeout = 15

私は保守的なアプローチをとっています。TIME_WAITを強引に解消するのではなく、キープアライブによって接続レートを低下させます。そうすることで、カーネルパラメータに深刻な影響が及ばず、動作も予測可能になります。.

アップストリームゾーン、バランサー戦略、およびDNSローテーション

ワーカーが複数ある場合、バランサーの状態を ゾーン, 、これにより障害や負荷が均一に保たれるようにします。キープアライブ・ソケットは引き続きワーカーごとに割り当てられますが、その分散がより均一になります。DNSを介して移動する動的なバックエンドの場合、私は「„resolve“ をサーバー行に追加し、 リゾルバー. 重要:IPがローテーションされる際、プールは古いソケットをすべて即座に再利用しない。したがって、私は keepalive_requests そして、刷新が迅速に効果を発揮するよう、現実的な範囲内で時間制限を設けること。.

upstream backend_pool {
    zone backend_zone 128k;  # でバランサーの状態を共有
    least_conn; # で、処理に時間がかかるリクエストを均等に分散

 server app-1.internal:8080 resolve;
    server app-2.internal:8080 resolve;

 keepalive 64;
    keepalive_requests 1000;
    keepalive_timeout 60s;
}

resolver 10.0.0.2 valid=30s;
resolver_timeout 5s;

proxy_next_upstream error timeout http_502 http_504;
proxy_next_upstream_tries 2;  # 少数の的を絞った再試行

特定のバックエンドノードにバインドされているセッション(例:スティッキー状態)については、再利用と以下を組み合わせています。 ip_hash あるいは外部のセッションメカニズム。これにより、コネクションプーリングがセッションの一貫性を損なうのを防ぐことができます。.

バックエンドへのTLS:SNI、セッションの再利用、および暗号スイート

バックエンドパスでTLSが頻繁に使用されるほど、キープアライブの価値は高まります。私はSNIを有効にし、予想される名前を指定して、TLSセッションの再利用を確保しています。これにより、ハンドシェイクのオーバーヘッドが低減され、レイテンシのピークが平滑化されます。 暗号スイートとプロトコルは、古いバックエンドを排除しない範囲で厳格に選択します。証明書検証(オプション)を行う場合は、信頼チェーンが完全でなければなりません。そうしないと、接続が散発的に切断されることになります。.

upstream https_backend {
    server backend.example.local:443;
    keepalive 32;
}

server {
    listen 443 ssl;

 location / {
 proxy_pass https://https_backend;
 proxy_http_version 1.1;
 proxy_set_header Connection "";

        proxy_ssl_server_name on;
 proxy_ssl_name backend.example.local;
 proxy_ssl_session_reuse on;
 proxy_ssl_protocols TLSv1.2 TLSv1.3;
        proxy_ssl_ciphers HIGH:!aNULL:!MD5;
 # optional: proxy_ssl_verify on;
 # optional: proxy_ssl_trusted_certificate /etc/nginx/ca.pem;
    }
}

バックエンド側を自分で管理している場合は、そこでセッションチケットやキャッシュを有効にし、メトリクスを使って再開率が向上しているかどうかを確認します。これをキープアライブと組み合わせることで、接続時間とハンドシェイク時間を恒久的に短縮することができます。.

特殊なケース:gRPC、WebSockets、および接続依存型認証

時点では ジーアールピーシー NGINXはHTTP/2を介してアップストリーム処理を行います。ここでは、ストリームの数が多い少数の長期接続が、多くの場合最良の結果をもたらします。接続プールは小規模ながら安定しています。 ウェブソケット アップグレード接続が誤って閉じられないように、readタイムアウトを長く設定し、mapソリューションのヘッダー処理ロジックはそのままにしておきます。. NTLM あるいは、接続に依存するその他の認証方式では、コネクション・ピニングが必要となります。私はそのような処理経路を個別のロケーションに分離し、そこでプーリングや再利用を制限することで、クライアント間でセキュリティ・ハンドシェイクが混在しないようにしています。.

# gRPC サンプル
location /grpc.Service/ {
    grpc_pass grpc://backend_pool;
    grpc_read_timeout 300s;  # の長いストリームを許可
}

重要なのは、パスごとに一貫した接続ポリシーを定め、キープアライブは意味的に重要でない場所でのみ広く適用することです。.

実務における測定可能性:アップストリーム・タイミングを含むアクセスログ

Accessログにアップストリームメトリクスを追加しています。これにより、レスポンスがプールされたソケットから来たものかどうか(接続時間が非常に短い)、およびバックエンドエラーがどのくらいの頻度で発生しているかを一目で把握できます。 さらに、相関関係を特定するために、接続番号と現在のクライアント接続経由のリクエスト数をログに記録しています。.

log_format upstream_timing '$remote_addr - $host "$request" '
 'up=$upstream_addr '
 'sc=$status usc=$upstream_status '
                           'cc=$connection cr=$connection_requests '
 'tc=$upstream_connect_time '
 'th=$upstream_header_time '
 'tr=$upstream_response_time';

access_log /var/log/nginx/access_upstream.log upstream_timing;

さらに、OSのステータスエンドポイントやソケット統計情報も活用しています。 正常な状態では、バックエンドへの接続率が低下し、upstream_connect_timeが短縮され、応答時間が安定し、接続リセットがほとんど発生しません。これと異なる場合は、ほぼ必ず、タイムリミットの設定が適切でないか、プールサイズが小さすぎる/大きすぎることを示しています。.

ロールアウト戦略とリスクの少ないチューニング

私は反復的なアプローチをとっています。小さなステップで進め、測定し、調整します。まずキープアライブを適度に有効にし、その後、タイムアウトとリクエスト数/接続数を調整します。変更は、アクティブな接続を切断することなく、ページを再読み込みすることで反映させます。こうすることでリスクを低く抑えられ、効果を明確に特定することができます。.

# 変更を検証し、ダウンタイムなしで読み込む
nginx -t && nginx -s reload

複数のアップストリームを運用している場合、最も重要なパスから順に、一つずつチューニングを行います。各段階には監視ウィンドウを設定し、メトリクスのパターンが明確に把握できるようにします。その後に初めて、値を調整します。.

リバースプロキシに関する簡潔なまとめ

私はHTTP/1.1を採用し、Connectionヘッダーを空にし、RPSではなく同時リクエスト数に基づいてプールサイズを決定しています。これにより、 パフォーマンス. `keepalive_requests` と `keepalive_timeout` を使って接続を最新の状態に保ち、古くなったソケットによる予期せぬトラブルを防いでいます。モニタリングにより、`upstream_connect_time` がゼロに近づいているか、バックエンドへの接続レートが低下していないかを確認します。 エラーが発生した場合は、まずプロトコルバージョン、ヘッダーの転送、タイムリミット、およびプールサイズを確認します。これにより、高負荷下でもNGINXプロキシを安定して稼働させることができます。 レスポンシブ かつ予測可能である。.

現在の記事

Redisのキー有効期限管理パフォーマンスが最適化された最新サーバー
データベース

Redisのキー有効期限に関するパフォーマンスの分析と最適化

適切なTTL戦略、エヴィクションポリシー、そして的確なモニタリングを活用して、Redisのキー有効期限管理のパフォーマンスを最適化し、キャッシュの安定性を維持する方法を学びましょう。焦点:Redisのキー有効期限管理。.