Nginx パフォーマンスチューニング実践:gzip、キャッシュ、接続プール設定
先週、アラートが鳴りました。EC サイトのトップページ読み込みが 4 秒まで伸びていたのです。Chrome DevTools を開くと、HTML が 120KB、CSS と JS でさらに 350KB——すべて未圧縮のまま。さらに悪いことに、リクエストはすべてバックエンドへ直撃し、キャッシュヒット率はわずか 12%。その夜残業して 2 時間、Nginx 設定を調整しました。gzip を有効化し、キャッシュ戦略を整え、接続プールのパラメータを見直したのです。翌朝確認すると、トップページ読み込みは 1.6 秒まで短縮。バックエンド QPS もほぼ半分に。
こういう問題、本当によくあります。Nginx を入れたらそのまま運用、gzip はデフォルト OFF、キャッシュは適当に 2 行、接続上限も初期値のまま——結果、トラフィックピークでサーバーが息切れする。
この記事では、本番環境で検証済みの Nginx パフォーマンスチューニング設定をまとめます。gzip で転送量を 60〜80% 削減、Brotli ならさらに 15〜25% 節約。キャッシュヒット率 95% でバックエンド負荷は 90% 減。接続プールを適切に設定すれば同時接続は 3〜4 倍。Thread Pools や reuseport などの応用手法を加えれば、単一サーバーの RPS は 50K〜80K まで伸ばせます。各モジュールの設定詳細、ハマりどころ、実測データまで包み隠さず説明します。
第 1 章:gzip / Brotli 圧縮設定 — 転送量を削減する
まず gzip がなぜ重要か。HTML が 100KB あると、gzip 後は 20〜25KB 程度になることも珍しくありません。省ける 75〜80KB の帯域は、ユーザーには速い読み込み、運用側には低い転送コストです。
初めて実感したのは、あるクライアント案件でした。モバイルユーザーが 60% 超、4G 環境からのアクセスが多い。トップ読み込み 3〜4 秒、直帰率 70% 超。gzip を入れたら転送量が 70% 減り、ファーストビューは 1.5 秒前後まで改善しました。
1.1 gzip 基本設定:まず動かす
Nginx の gzip 設定はシンプルです。要は次の数行:
http {
gzip on;
gzip_vary on;
gzip_min_length 1000;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml;
}
gzip on はスイッチです。gzip_vary on は重要で、レスポンスヘッダーに Vary: Accept-Encoding を付けます。CDN とブラウザに「クライアントの圧縮対応に応じて内容が変わる」と伝え、キャッシュの取り違えを防ぎます。
gzip_min_length 1000 は 1KB 未満は圧縮しない、という意味。小さすぎるファイルは CPU だけ消費して得が少ない。gzip_types で圧縮対象 MIME を指定します。デフォルトは text/html のみなので、CSS、JS、JSON、XML などを追加してください。
1.2 gzip 応用設定:圧縮レベルと MIME タイプ一覧
圧縮レベルはトレードオフです。Nginx の gzip_comp_level は 1〜9。数字が大きいほど圧縮率は上がるが、CPU も増えます。
こちらで計測した結果:
| 圧縮レベル | HTML 圧縮率 | CPU 時間(ms) | 推奨シーン |
|---|---|---|---|
| 1 | 65% | 2 | CPU が逼迫 |
| 4 | 72% | 3 | バランス型(推奨) |
| 6 | 75% | 5 | 帯域が逼迫(推奨) |
| 9 | 78% | 12 | 極端なケース |
率直に言うと、レベル 4 と 6 が大多数の最適解です。レベル 9 は CPU が倍増するのに、圧縮率は数ポイントしか伸びません。
本番で使っている gzip 設定の全体像:
# gzip 圧縮設定
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_min_length 1000;
gzip_types
text/plain
text/css
text/xml
text/javascript
application/json
application/javascript
application/xml
application/xml+rss
application/xhtml+xml
application/x-javascript;
gzip_disable "msie6";
gzip_proxied any は見落とされがちです。Nginx がリバースプロキシで、バックエンドレスポンスに Content-Length がない場合、デフォルトでは圧縮されません。any にすると条件を満たすレスポンスを強制圧縮できます。
gzip_disable "msie6" は古い IE6 向け。今はほぼ不要ですが、念のため残しています。
1.3 どのファイルタイプが最も効く?
実測では、ファイルタイプごとに効果が大きく異なります:
| ファイルタイプ | 元サイズ | 圧縮後 | 圧縮率 |
|---|---|---|---|
| HTML | 100KB | 20-25KB | 75-80% |
| CSS | 80KB | 24-28KB | 65-70% |
| JavaScript | 120KB | 36-42KB | 65-70% |
| JSON API | 50KB | 20-25KB | 50-60% |
| 画像 / 動画 | 既に圧縮済み | 意味なし | 0-5% |
画像・動画は JPEG、PNG、MP4 などで既に圧縮済み。さらに gzip すると逆に肥大化することも。gzip_types に image/* や video/* を入れないでください。
ある案件で gzip_types に image/jpeg が入っていて、画像が 3〜5% 膨らんでいました。初心者の頃、私も MIME を全部入れようとしたことがあります。
1.4 Brotli:gzip よりさらに 15〜25% 節約
さらに踏み込むなら Brotli。Google 製の圧縮アルゴリズムで、同レベルなら gzip より 15〜25% 高い圧縮率。静的リソース向きで、ブラウザ対応も広がっています。
ただし Brotli は Nginx 標準モジュールではありません。追加ビルドか動的モジュールが必要。私は公式動的モジュールで、Nginx の再コンパイルなしで導入しています:
# 動的モジュール利用時は先に load
load_module modules/ngx_http_brotli_filter_module.so;
load_module modules/ngx_http_brotli_static_module.so;
http {
brotli on;
brotli_comp_level 6;
brotli_types text/plain text/css application/javascript application/json;
brotli_min_length 256;
}
Brotli の圧縮レベルは 1〜11。動的コンテンツは 6 程度が無難。11 など高レベルは時間がかかりすぎます。静的ファイルは事前に最高レベルで圧縮し、Nginx は .br を返す方式も有効です。
実測比較:
| 圧縮方式 | 100KB HTML 圧縮後 | 圧縮時間 | ブラウザ対応 |
|---|---|---|---|
| gzip (level 6) | 25KB | 5ms | ほぼ全て |
| Brotli (level 6) | 18KB | 15ms | 95%+ |
| Brotli(事前圧縮 level 11) | 15KB | 0 | 95%+ |
動的コンテンツは Brotli level 4〜6、静的は事前圧縮。Nginx ビルドが面倒なら gzip でも 75% 圧縮は十分な成果です。
第 2 章:キャッシュ戦略 — 静的コンテンツを加速
キャッシュはパフォーマンスチューニングで最も効果が出やすい領域。設定が合えば 95% のリクエストを Nginx から返せ、バックエンドに届きません。バックエンドが汗をかいているのに Nginx キャッシュがほぼ空——「未設定」ではなく「誤設定」のケースが多いです。
2.1 proxy_cache と fastcgi_cache の選び方
Nginx には 2 種類のキャッシュがあります:
- proxy_cache:上流サーバーのレスポンスをキャッシュ。リバースプロキシ(Node.js、Python、Go など)向け
- fastcgi_cache:FastCGI プロセスのレスポンスをキャッシュ。PHP-FPM 向け
バックエンドの技術スタックで選びます。PHP なら fastcgi_cache、Node.js / Python / Go なら proxy_cache。設定ロジックはほぼ同じなので、以下は proxy_cache を例に説明します。
2.2 proxy_cache の完全設定
まず http ブロックでキャッシュパスを定義:
http {
proxy_cache_path /var/cache/nginx
levels=1:2
keys_zone=my_cache:10m
max_size=10g
inactive=60m
use_temp_path=off;
}
各行の意味:
levels=1:2:2 階層ディレクトリ。1 ディレクトリにファイルが集中するのを防ぐkeys_zone=my_cache:10m:ゾーン名とメタデータ用メモリ。10m で約 8 万キーmax_size=10g:キャッシュ総量上限。超過分は LRU で削除inactive=60m:60 分アクセスがなければ削除use_temp_path=off:一時ファイル経由せず直接書き込み
server または location で有効化:
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://backend;
proxy_cache my_cache;
# キャッシュ有効期間
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
proxy_cache_valid any 1m;
# キャッシュキー設計
proxy_cache_key $scheme$request_method$host$request_uri;
# フォールバック戦略
proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504;
# デバッグ用キャッシュ状態ヘッダー
add_header X-Cache-Status $upstream_cache_status;
}
}
proxy_cache_valid が肝です:
200 302 10m:正常レスポンスは 10 分404 1m:404 は 1 分(悪意あるリクエストのバックエンド直撃を防ぐ)any 1m:その他ステータスは 1 分
2.3 キャッシュキー設計と失効戦略
proxy_cache_key が「同一リクエスト」の定義を決めます。デフォルトは $scheme$proxy_host$request_uri ですが、明示指定を推奨:
proxy_cache_key $scheme$request_method$host$request_uri;
プロトコル、HTTP メソッド、ホスト名、完全 URI を含めます。GET / POST 混在や複数ドメインでは精度が上がります。
失効は悩ましいところ。よく使う戦略:
- 時間失効:
proxy_cache_validで期限切れ - 能動的バイパス:
proxy_cache_bypassでキャッシュを迂回 - パージ:Nginx Plus の
proxy_cache_purge
私は 2 番目をよく使い、リクエストヘッダーで制御します:
# 特定ヘッダーでキャッシュバイパス
proxy_cache_bypass $http_x_nocache;
# クエリパラメータでもバイパス
proxy_cache_bypass $arg_nocache;
キャッシュ更新時は ?nocache=1 や X-Nocache: 1 ヘッダーで十分です。
2.4 フォールバック:バックエンド障害時も配信
proxy_cache_use_stale は実用的です。バックエンドエラーやタイムアウト時、期限切れキャッシュを返してエラーを避けられます。
proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504;
昨年のダブルイレブン(独身の日セール)で、バックエンド拡張中に API が断続的 502。この設定のおかげでユーザー影響は最小限——数分古いキャッシュでも内容は表示できました。復旧後は自動更新。
実測比較:
| 指標 | キャッシュなし | キャッシュ HIT | フォールバック |
|---|---|---|---|
| 応答時間 | 150-200ms | 5-10ms | 5-10ms |
| バックエンド QPS | 1000 | 50 | 0 |
| ユーザー体験 | 正常 | 正常 | やや古い |
HIT 時は 200ms → 5〜10ms、約 20 倍の改善。体感しやすい効果です。
2.5 マイクロキャッシュ:動的コンテンツも加速
動的=キャッシュ不可、と思いがちですが、1〜5 秒のマイクロキャッシュなら有効。瞬間的な高負荷でもバックエンド負荷を大きく下げられます。
EC トップページで試しました。リアルタイムレコメンドと在庫表示で完全動的。セール期間のトラフィック急増でバックエンドが限界。5 秒マイクロキャッシュを追加:
proxy_cache_path /var/cache/nginx/micro levels=1:2 keys_zone=micro:10m max_size=1g;
location / {
proxy_cache micro;
proxy_cache_valid 200 5s; # 5 秒だけキャッシュ
proxy_cache_lock on; # 更新中の同時リクエスト殺到を防ぐ
proxy_cache_background_update on; # バックグラウンドで非同期更新
}
proxy_cache_lock on が重要。期限切れ時、最初の 1 リクエストだけバックエンドへ。他は古いキャッシュを待つので、「失効直後に一斉バックエンド直撃」が起きません。
効果は顕著。トップ TTFB は 800ms → 5ms 前後、バックエンド QPS は 2000 → 400。5 秒の遅延はユーザーにはほぼ無感知、サーバー負荷は大幅軽減。
2.6 条件付きリクエスト:帯域節約
proxy_cache_revalidate を有効にすると、If-Modified-Since / If-None-Match でバックエンドに検証します。304 Not Modified なら本体再転送なし、メタデータだけ更新。
proxy_cache_revalidate on;
大きなファイルで更新頻度が低い場合に特に有効。帯域を大きく節約できます。
第 3 章:接続プール設定 — 高トラフィックの必須要素
gzip とキャッシュは「どう速く届けるか」、接続プールは「どう多くさばくか」。デフォルトでは 1 worker あたり最大 1024 接続。トラフィックが来るとすぐ足りなくなります。
3.1 worker_connections:上限を計算する
最大同時接続数の式:
最大同時接続 = worker_processes × worker_connections
8 コア CPU で worker_processes を 8(または auto)、worker_connections を 4096 とすると:
最大同時接続 = 8 × 4096 = 32768
大きく見えますが、1 リクエストでクライアント↔Nginx と Nginx↔バックエンドの 2 接続を使うことが多い。実際にさばける同時リクエストはおおよそ半分程度と見てください。
events ブロックで設定:
events {
worker_connections 4096;
use epoll;
multi_accept on;
}
Linux では use epoll はデフォルトですが、明示しても問題ありません。multi_accept on は worker が複数接続を同時 accept し、高トラフィック時の待ち行列を減らします。
3.2 クライアント keepalive:接続再利用
TCP 確立は 3-way ハンドシェイクのコストがあります。keepalive でクライアントと Nginx の接続を再利用できます。
http {
keepalive_timeout 65;
keepalive_requests 1000;
}
keepalive_timeout 65:65 秒アイドルで切断。長すぎるとリソース占有、短すぎると再利用効果が薄い。60〜75 秒が無難。
keepalive_requests 1000:1 接続で最大 1000 リクエスト。小さすぎると頻繁切断、大きすぎるとリークリスク。1000 は安定した値です。
新パラメータ keepalive_time で、リクエスト数に関係なく接続の最大生存時間を制限できます。長時間稼働で接続が溜まる場合:
keepalive_time 1h; # 1 接続の最大生存 1 時間
3.3 upstream keepalive:バックエンド接続プール
知らない人が多いですが、効果は大きい設定。Nginx とバックエンド間も接続を再利用し、TCP 確立のオーバーヘッドを減らします。
upstream backend {
server 127.0.0.1:8080;
server 127.0.0.1:8081;
keepalive 64;
keepalive_timeout 60s;
keepalive_requests 1000;
}
server {
location / {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
}
}
keepalive 64:アイドル接続 64 本をプール。バックエンド台数の 4〜8 倍程度が目安。
proxy_http_version 1.1 と proxy_set_header Connection "" は必須。HTTP/1.1 で keepalive を使い、Connection ヘッダーを空にしないと接続は毎回閉じられます。
実測比較:
| 設定 | 接続確立回数 / 分 | CPU 負荷 | 推奨シーン |
|---|---|---|---|
| upstream keepalive なし | 6000 | 高 | 低トラフィック |
| keepalive 32 | 3000 | 中 | 中トラフィック |
| keepalive 64 | 1500 | 低 | 高トラフィック |
upstream keepalive で接続確立コストは約 50% 削減。高トラフィックほど重要です。
3.4 ファイル記述子上限:OS 層も忘れずに
Nginx の接続数は OS のファイル記述子上限に縛られます。worker_connections を 4096 にしても、プロセス上限が 1024 なら意味がありません。
現在値の確認:
ulimit -n
65536 未満なら /etc/security/limits.conf を編集:
* soft nofile 65536
* hard nofile 65536
Nginx 設定にも宣言:
worker_rlimit_nofile 65536;
main ブロック(worker_processes と同階層)に置き、起動時に十分な記述子を確保します。
3.5 推奨パラメータ早見表
シーン別の目安:
| パラメータ | 低トラフィック(<1000 QPS) | 中(1000-5000 QPS) | 高(>5000 QPS) |
|---|---|---|---|
| worker_processes | auto | auto | auto |
| worker_connections | 1024 | 2048 | 4096 |
| keepalive_timeout | 60 | 65 | 75 |
| keepalive_requests | 100 | 500 | 1000 |
| upstream keepalive | 16 | 32 | 64 |
| worker_rlimit_nofile | 4096 | 8192 | 65536 |
あくまで出発点。wrk や ab で負荷テストし、接続数と応答時間の曲線から最適値を探してください。
第 4 章:応用最適化 — Thread Pools と reuseport
前 3 章で大多数のケースはカバーできます。トラフィックがさらに大きい(単機 RPS 50K 超)か、レイテンシに敏感なら、次の 2 つも検討余地あり。
4.1 Thread Pools:sendfile のボトルネック突破
Nginx は基本、シングルスレッドのイベント駆動。多くの場面で十分高速ですが、高トラフィックの静的配信では sendfile に隠れた壁があります。ゼロコピーでも、ファイル読み込みと socket 書き込みが同一 worker で完結し、ディスク I/O が遅いと worker 全体がブロックされます。
Thread Pools はファイル I/O を別スレッドプールへ逃がし、worker はスケジューリングに専念します。
Nginx 公式ブログの事例では、1MB ファイル配信で約 9 倍の性能向上。ディスク I/O 制限がボトルネックだったケースです。
設定例:
http {
thread_pool default threads=32 max_queue=65536;
aio threads=default;
sendfile_max_chunk 512k;
}
threads=32 はプール内スレッド数、max_queue=65536 は待ち行列上限。aio threads=default で非同期 I/O を有効化。sendfile_max_chunk 512k は 1 回の送信チャンクサイズ。
万能ではありません。API 中心でディスク I/O がボトルネックでなければ、コンテキストスイッチだけ増える可能性。静的配信・大ファイルダウンロード向けと考えてください。
4.2 Socket Sharding(reuseport):接続レイテンシ低減
Nginx 1.9.1 から reuseport で、複数 worker が同一ポートを独立 listen できます。worker 間の accept ロック競合を避けられます。
従来は全 worker が 1 つの listen socket を共有し、新接続で accept mutex を争います。高トラフィックではロック競合でレイテンシが揺れます。
reuseport 有効時:
server {
listen 80 reuseport;
}
各 worker が独立 listen socket を持ち、カーネルが接続を分散。ロック競合ゼロ。
実測(Nginx 公式ブログ):
| 指標 | reuseport なし | reuseport あり |
|---|---|---|
| 平均レイテンシ | 15.65ms | 12.35ms |
| レイテンシ標準偏差 | 3.5ms | 1.2ms |
| 接続分布 | 偏りあり | 均等 |
レイテンシ約 21% 改善。揺れの減少がより重要。QPS 20K 超で効果が顕著、低トラフィックでは体感しにくいことも。
4.3 open_file_cache:ファイル記述子キャッシュ
静的配信では open_file_cache で fd とメタデータをキャッシュし、毎リクエストのディスク stat を減らせます:
http {
open_file_cache max=10000 inactive=30s;
open_file_cache_valid 60s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
}
max=10000:最大 1 万ファイル分の情報inactive=30s:30 秒未アクセスで削除open_file_cache_valid 60s:60 秒ごとに有効性チェックopen_file_cache_errors on:ファイル不存在などのエラーもキャッシュ
静的サイト向け。動的コンテンツでファイルが頻繁に変わる場合は、古い内容が残るリスクがあるので非推奨。
第 5 章:統合設定テンプレート — 本番ですぐ使える
原理は前章まで。ここでは統合テンプレートを提示します。パラメータは調整してくださいが、骨格は共通です。
# nginx.conf 本番テンプレート(高トラフィック向け)
user nginx;
worker_processes auto;
worker_rlimit_nofile 65536;
events {
worker_connections 4096;
use epoll;
multi_accept on;
}
http {
# gzip 圧縮設定
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_min_length 1000;
gzip_types text/plain text/css text/xml text/javascript
application/json application/javascript application/xml
application/xml+rss application/xhtml+xml;
gzip_disable "msie6";
# キャッシュパス
proxy_cache_path /var/cache/nginx
levels=1:2
keys_zone=my_cache:10m
max_size=10g
inactive=60m
use_temp_path=off;
# クライアント接続
keepalive_timeout 65;
keepalive_requests 1000;
keepalive_time 1h;
# ファイルキャッシュ(静的サイト向け・任意)
open_file_cache max=10000 inactive=30s;
open_file_cache_valid 60s;
open_file_cache_min_uses 2;
# バックエンドサーバーグループ
upstream backend {
server 127.0.0.1:8080;
server 127.0.0.1:8081;
keepalive 64;
keepalive_timeout 60s;
keepalive_requests 1000;
}
server {
listen 80 reuseport;
server_name example.com;
location / {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
# キャッシュ設定
proxy_cache my_cache;
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
proxy_cache_key $scheme$request_method$host$request_uri;
proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504;
proxy_cache_revalidate on;
# デバッグ用レスポンスヘッダー
add_header X-Cache-Status $upstream_cache_status;
}
}
}
3 シーン別の差分設定
EC サイト:トップ・商品詳細は更新頻度が高め。キャッシュ 10〜15 分程度。DB クエリが多くバックエンド負荷が大きいので upstream keepalive は大きめ。セール期間は 1〜3 秒のマイクロキャッシュも有効。
API サービス:リアルタイム性重視で proxy_cache_valid は 1〜5 分程度。JSON への gzip 効果は大きいので必須。Brotli が入れられればより良い。レスポンスは小さいがリクエスト頻度が高く、圧縮の累積効果が大きい。
静的サイト:HTML / CSS / JS はほぼ不変。キャッシュ 1 時間以上も可。テキスト多めで gzip 効果最大。open_file_cache と Thread Pools も検討。fd キャッシュと非同期 I/O が効きます。
性能改善比較(更新版)
| 設定項目 | 最適化前 | 最適化後 | 改善率 |
|---|---|---|---|
| HTML 転送量(gzip) | 100KB | 25KB | 75% ↓ |
| HTML 転送量(Brotli) | 100KB | 18KB | 82% ↓ |
| API 応答時間(キャッシュ HIT) | 200ms | 8ms | 96% ↓ |
| 同時接続能力 | 1000 | 4000 | 4x ↑ |
| RPS(単機最適化後) | 10K | 50K-80K | 5-8x ↑ |
| TTFB(reuseport) | 15.65ms | 12.35ms | 21% ↓ |
実測と公式ドキュメントを踏まえた数値です。サーバー構成・ネットワーク・業務特性で変わるので、必ず負荷テストで確認してください。
第 6 章:よくある問題とトラブルシュート
遭遇頻度の高い問題と対処法です。
Q:gzip が効かず、Content-Encoding: gzip が出ない
確認 3 点:
gzip onが正しい階層(http ブロック)にあるかgzip_typesにレスポンス MIME が含まれるか- レスポンスサイズが
gzip_min_lengthより大きいか
curl テスト:curl -H "Accept-Encoding: gzip" -I http://your-site.com
Q:キャッシュヒット率が低く、X-Cache-Status がほぼ MISS
よくある原因:
- キャッシュキー設計の不備で、毎回「別リクエスト」扱い
proxy_cache_validが短すぎて使う前に失効- バックエンドが
Cache-Control: no-cacheやSet-Cookieを返している
レスポンスヘッダーでキャッシュ禁止がないか確認。
Q:worker_connections 不足で 502
Nginx エラーログに worker_connections are not enough があれば同時接続超過。
対処:
worker_connectionsを増やす- 接続リーク(keepalive 設定ミス)を調査
- サーバー台数を増やしてロードバランシング
Q:gzip と sendfile は競合する?
競合しません。gzip はレスポンス内容の圧縮、sendfile はファイル転送方式。両方有効化可能。動的コンテンツの gzip はメモリ上で圧縮し sendfile 経由にならない点だけ注意。静的の事前圧縮ファイルは sendfile 可。
Q:upstream keepalive が効かない?
典型原因 2 つ:
proxy_http_version 1.1の欠落proxy_set_header Connection ""の欠落
この 2 行は location ブロックに。upstream ブロックではありません。
Q:reuseport で “duplicate listen options” エラー
reuseport は listen 行に 1 回だけ。他で重複しないこと。同一ポートの複数 server それぞれに reuseport が必要な場合もあります。
Q:メモリ使用量が高く OOM が頻発
考えられる原因:
proxy_cache_pathのkeys_zoneが大きすぎる- キャッシュファイル過多でメモリマップが膨らむ
keepaliveプールが大きすぎてアイドル接続が残る
パラメータを下げるか、メモリ増設を検討。
まとめ
Nginx パフォーマンスチューニングの本質は、圧縮・キャッシュ・接続プールの 3 点。Brotli、マイクロキャッシュ、Thread Pools、reuseport を加えれば、単機 RPS を 10K から 50K〜80K へ引き上げられます。
一度きりで終わりではありません。次の順序を推奨します:
- まず gzip:変更最小、効果最大。10 分程度
- 次にキャッシュ:業務に合わせた戦略設計。1 日以内
- 接続プール調整:負荷テスト必須。トラフィック安定後
- 応用最適化:Thread Pools と reuseport。特に大流量向け
変更のたびに wrk や ab で応答時間・QPS・エラー率を確認。感覚ではなくデータで判断してください。
最終チェックリスト:
- gzip 有効、MIME タイプ設定完備
- gzip_comp_level を 4〜6 に(CPU と圧縮率のバランス)
- Brotli 設定済み(利用可能なら)
- proxy_cache_path 設定、キャッシュサイズ妥当
- proxy_cache_valid を業務に合わせて設定
- マイクロキャッシュ有効(高負荷の動的コンテンツ)
- proxy_cache_use_stale フォールバック設定済み
- worker_connections を 4096 以上
- keepalive_timeout を 60〜75 秒
- upstream keepalive 設定(HTTP/1.1 と Connection ヘッダー含む)
- reuseport 有効(高トラフィック)
- ファイル記述子上限引き上げ(65536)
- デバッグ用 X-Cache-Status ヘッダー付与
以上です。質問があればコメントでどうぞ。可能な限り返信します。
FAQ
gzip 圧縮が効かず、レスポンスヘッダーに Content-Encoding: gzip が出ない場合は?
キャッシュヒット率が低く、X-Cache-Status がほとんど MISS の場合の切り分けは?
worker_connections が足りず 502 エラーが出る場合は?
upstream keepalive が効かない典型的な原因は?
Brotli と gzip はどう選ぶ?
トラフィック規模別の推奨パラメータは?
8分で読めます · 公開日: 2026年5月15日 · 更新日: 2026年6月8日
関連記事
Nginx リバースプロキシ完全ガイド:upstream・バッファ・タイムアウト
Nginx リバースプロキシ完全ガイド:upstream・バッファ・タイムアウト
Nginx パフォーマンスチューニング:gzip、キャッシュ、接続プール設定
Nginx パフォーマンスチューニング:gzip、キャッシュ、接続プール設定
Nginx SSL/TLS 設定実践:HTTPS 証明書から A+ セキュリティ強化まで
コメント
GitHubアカウントでログインしてコメントできます