Nginxバッファチューニング: `client_body_buffer_size`と`proxy_buffer_size`の最適化

バッファチューニングを習得してNginxのパフォーマンスを最適化しましょう。このガイドでは、`client_body_buffer_size`、`proxy_buffer_size`、および`proxy_buffers`を設定して、アップロード時とレスポンス処理時の低速なディスクI/Oを最小限に抑える方法を詳しく説明します。実践的な例を通して、データが高速なメモリバッファに保持され、高スループットアプリケーションのレイテンシが向上する方法を学びましょう。

50 ビュー

Nginxバッファチューニング: client_body_buffer_size および proxy_buffer_size の最適化

Nginxは、その高性能、効率性、スケーラビリティで広く知られており、堅牢なリバースプロキシ、ロードバランサー、またはウェブサーバーとして頻繁に利用されます。ピークパフォーマンスを達成する上で重要な側面の一つは、Nginxの内部バッファリングメカニズムを正しく設定することです。バッファは、Nginxが受信リクエストボディ(アップロードやPOSTデータ用)および送信アップストリームレスポンスをどのように処理するかを決定します。設定ミスは、過剰なメモリ消費や、逆に低速なディスクI/O操作を引き起こし、Nginxの速度の利点を打ち消してしまう可能性があります。

このガイドでは、主要なバッファディレクティブである client_body_buffer_sizeproxy_buffer_size、および関連する設定について深く掘り下げ、その機能、影響を説明し、特定のワークロードに合わせてそれらをチューニングするための実践的な手順を提供します。効果的なバッファチューニングは、不要なディスクへのデータスワップを防ぎ、レスポンスの遅延と全体的なスループットを直接改善します。

Nginxバッファリングの基本を理解する

Nginxは、クライアントからサーバーへ、またはサーバーからバックエンドのアップストリームアプリケーションへ流れるデータを一時的に保持するためにバッファを使用します。

バッファが満杯になった場合、Nginxはメモリでバッファリングを続けるか、超過データをディスク上の一時ファイルに書き出すかを決定しなければなりません。ディスクI/Oはメモリアクセスよりも大幅に遅いため、チューニングの目標は、標準的なリクエスト/レスポンスサイズがメモリバッファに快適に収まるようにすることです。

主要なバッファディレクティブの概要

いくつかのディレクティブがバッファリングを制御しており、それらはコンテキスト(クライアント通信、プロキシ、FastCGI)に応じて異なります。

  • client_body_buffer_size: クライアントリクエストボディ(POSTリクエスト、ファイルアップロードなどで使用)の読み取りに使用されるバッファのサイズを制御します。
  • proxy_buffer_size: リバースプロキシとして機能する際に、アップストリームサーバーからのレスポンスを読み取るために使用されるバッファのサイズを制御します。
  • proxy_buffers: データが proxy_buffer_size を超える場合に、アップストリームサーバーからのレスポンスを読み取るために使用されるバッファの数とサイズを定義します。
  • fastcgi_buffer_size および fastcgi_buffers: FastCGI通信(例:PHP-FPM)に特化した同様のディレクティブです。

client_body_buffer_size のチューニング

このディレクティブは、Nginxが大規模なアップロードや広範なフォーム送信を直接処理する場合に非常に重要です。

デフォルトの動作と影響

デフォルトでは、Nginxは通常 client_body_buffer_size を比較的小さい値(バージョンによって8kまたは16k)に設定します。クライアントリクエストボディがこのサイズを超えると、Nginxは超過データをディスク上の一時ファイル(client_body_temp_path)に書き込み始めます。

影響: デフォルトのバッファサイズよりも大きく、かつ利用可能なRAMの範囲内のリクエストを処理すると予想される場合、この値を増やすことで、遅いディスクへの書き込みを防ぐことができます。

設定例

このディレクティブは、httpserver、または location コンテキスト内に設定されます。

http {
    # クライアントリクエストボディのバッファサイズを128KBに設定
    client_body_buffer_size 128k;
    ...
}

ベストプラクティス: この値は、許可される絶対最大アップロードサイズではなく、予想されるPOSTデータの最大典型サイズに基づいて設定してください。グローバルに高すぎると設定すると、多数のクライアントが中程度の大きさのリクエストを同時に送信した場合、すべてのワーカープロセスで過剰なメモリを消費するリスクがあります。

リバースプロキシバッファの最適化: proxy_buffer_sizeproxy_buffers

Nginxがリバースプロキシとして機能する場合、主な関心は、アップストリームサーバー(例:Apache、Tomcat、またはNode.jsアプリケーション)から返されるレスポンスのバッファリングに移ります。

proxy_buffer_size

これは、レスポンスヘッダーとレスポンスボディの最初のチャンクをアップストリームサーバーから読み取るために使用される初期バッファサイズを定義します。

proxy_buffers (数とサイズ)

アップストリームのレスポンスボディが大きい場合、Nginxは proxy_buffers で定義された一連のバッファを使用します。このディレクティブは2つの引数を取ります。

  1. バッファの
  2. 各バッファのサイズ

レスポンスデータが割り当てられた総バッファスペース(数 × サイズ)を超えると、Nginxは残りのデータを proxy_temp_path ディレクトリ内のディスクに書き込み始めます。

設定例(プロキシコンテキスト)

アップストリームサーバーからの大きなレスポンスがメモリ内に保持されるようにするには、プロキシバッファを次のように設定します。

location /api/ {
    proxy_pass http://backend_servers;

    # 初期バッファサイズを64kに設定
    proxy_buffer_size 64k;

    # 残りのレスポンスには、それぞれ128kのサイズのバッファを8つ使用します。
    # 総バッファ容量:8 * 128k = 1MB
    proxy_buffers 8 128k;

    # Nginxがクライアントにデータを送信し始める前に、一時的にディスクに書き込むことができる最大サイズを設定します
    proxy_max_temp_file_size 10m;
}

ヒント: バックエンドが通常、大きなJSONペイロードや大きな静的ファイルを返す場合は、標準的なレスポンスサイズを調査し、それらのレスポンスの95%をカバーするのに十分な大きさの proxy_buffers を設定してください。アップストリームサーバーが大きなレスポンスヘッダーを送信する場合は、proxy_buffer_size を増やす必要があるかもしれません。

ディスクスピリングの管理 (proxy_max_temp_file_size)

Nginxのメモリバッファスペース(proxy_buffers または client_body_buffer_size で定義された)が不足すると、オーバーフローをディスクに書き出します。これがいつ発生するかを制御するディレクティブは *_temp_file_size です。

デフォルトでは、Nginxは一時ファイルが無限に成長することを許可しており、高負荷時にディスクスペースを急速に消費する可能性があります。

proxy_max_temp_file_size

これは、アップストリームレスポンスをバッファリングする際にNginxが作成できる一時ファイルのサイズを制限します。これを 0 に設定すると、一時ファイルの使用が完全に無効になり、バッファが超過した場合にNginxにメモリでバッファリングさせるか、エラーを返すか(またはコンテキストに応じて接続を閉じるか)を強制します。

# 例:バッファリングがメモリを超過した場合、20MB後にディスクへの書き込みを停止
proxy_max_temp_file_size 20m;

# 例:ディスクへのスピリングを完全に無効にする(注意して十分なRAMとともに使用)
proxy_max_temp_file_size 0;

proxy_max_temp_file_size 0 に関する警告: これはディスクI/Oを排除しますが、ワーカープロセスが割り当てられた総バッファスペースを超える多数の同時リクエストを処理する場合、Nginxがデータストリームを処理できないと、メモリ枯渇エラーや予期しない接続切断に直面する可能性があります。

FastCGIバッファのチューニング (fastcgi_buffer_size)

FastCGI(PHPなど)を介して通信するアプリケーションの場合、バッファリングロジックは似ていますが、専用のディレクティブを使用します。

fastcgi_buffer_size は、ヘッダーとFastCGIレスポンスの最初の部分を読み取るためのバッファサイズを設定します。fastcgi_buffers は、後続のボディデータを読み取るために使用されるバッファの配列を定義します。

location ~ \.php$ {
    include fastcgi_params;
    fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;

    # FastCGIバッファをそれぞれ16kのバッファ16個に設定
    fastcgi_buffers 16 16k;

    # レスポンスが非常に大きい場合は、サイズを調整
    fastcgi_buffer_size 128k;
}

まとめとチューニング戦略

効果的なバッファチューニングは、システムメモリの可用性とワークロードの特性との間のバランスをとる行為です。

  1. ワークロードの分析: クライアントリクエストボディとアップストリームレスポンスの標準的なサイズを決定します。
  2. クライアントボディ: client_body_buffer_size を、最大の典型的なPOST/アップロードサイズをカバーするように設定します。
  3. プロキシレスポンス: proxy_buffers(数とサイズ)を、ほとんどのバックエンドレスポンスをRAMに収容するのに十分な大きさにする。
  4. スピリングの制限: proxy_max_temp_file_size を使用して、バッファオーバーフローによるディスク使用量を制限するか、メモリ割り当てが十分であると確信している場合にのみ 0 に設定します。

設定変更後はパフォーマンスを徹底的にテストし、システムメモリ使用率を監視することを忘れないでください。

# nginx.confを変更した後は、常にリロードする前に構文をテストしてください
nginx -t

# その後、Nginxをリロードして、接続を切断することなく変更を適用します
systemctl reload nginx