2026年6月18日

2026年6月18日

Nginxのキャッシュ設定(proxy_cache)でパフォーマンスを向上させる方法

はじめに

Nginxをリバースプロキシとして使っているがバックエンドへの負荷が高い・proxy_cacheを設定したがキャッシュが効いているか確認できない・特定のURLはキャッシュしたくない・キャッシュを手動でクリアしたいといった問題の解決方法を解説します。

症状・原因

  • proxy_cacheを設定したがレスポンスにX-Cache-Status: MISSしか表示されない(キャッシュが機能していない)
  • ログイン済みユーザーにもキャッシュされたページが表示される(バイパス設定漏れ)
  • キャッシュの有効期間が設定されていないため、バックエンドからCache-Control: no-storeが返るとキャッシュされない
  • キャッシュファイルがディスクを圧迫している(max_sizeが未設定)

解決手順

ステップ1:proxy_cache の設定を確認する

# ✅ 現在のキャッシュ設定を確認
sudo nginx -T | grep -A 10 "proxy_cache"

# ✅ キャッシュファイルの状態を確認
ls -lh /var/cache/nginx/
du -sh /var/cache/nginx/

# ✅ レスポンスヘッダーでキャッシュ状態を確認
curl -sI http://example.com/ | grep -i cache
# → X-Cache-Status: HIT    ← キャッシュヒット
# → X-Cache-Status: MISS   ← キャッシュなし(初回アクセス)
# → X-Cache-Status: BYPASS ← キャッシュをバイパス
# → X-Cache-Status: EXPIRED ← 期限切れ(再取得)

ステップ2:proxy_cache の基本設定

# ✅ /etc/nginx/nginx.conf の http ブロックに追加
http {
    # ✅ キャッシュゾーンの定義
    proxy_cache_path /var/cache/nginx
        levels=1:2                  # ディレクトリ階層
        keys_zone=MAIN_CACHE:10m   # ゾーン名:メタデータ用メモリ
        inactive=60m               # 60分アクセスがなければ削除
        max_size=10g               # 最大10GBまでキャッシュ
        use_temp_path=off;         # 一時ファイルを使わない(パフォーマンス向上)

    # ✅ proxy_cache キーの定義
    proxy_cache_key "$scheme$proxy_host$request_uri";
}
# ✅ /etc/nginx/sites-available/example.conf
server {
    listen 443 ssl http2;
    server_name example.com;

    location / {
        proxy_pass http://backend:8080;

        # ✅ キャッシュゾーンを指定
        proxy_cache MAIN_CACHE;

        # ✅ ステータスコード別のキャッシュ有効期間
        proxy_cache_valid 200 301 302  10m;  # 成功/リダイレクト: 10分
        proxy_cache_valid 404          1m;   # 404: 1分
        proxy_cache_valid any          0s;   # それ以外: キャッシュしない

        # ✅ バックエンドのCache-Controlを無視してキャッシュ
        proxy_ignore_headers Cache-Control Expires;

        # ✅ キャッシュ状態をヘッダーで通知
        add_header X-Cache-Status $upstream_cache_status;

        # ✅ 標準プロキシヘッダー
        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;
    }
}

ステップ3:キャッシュのバイパス設定

# ✅ 条件に応じてキャッシュをバイパスする
server {
    # ✅ バイパス条件の定義
    set $no_cache "";

    # Cookie でログイン済みユーザーを検出
    if ($http_cookie ~* "session=|wordpress_logged_in=|user_token=") {
        set $no_cache "1";
    }

    # 管理ページはキャッシュしない
    if ($request_uri ~* "^/admin|^/dashboard|^/wp-admin") {
        set $no_cache "1";
    }

    # POST リクエストはキャッシュしない
    if ($request_method = POST) {
        set $no_cache "1";
    }

    location / {
        proxy_pass http://backend:8080;
        proxy_cache MAIN_CACHE;
        proxy_cache_valid 200 10m;

        # ✅ $no_cache が "1" の場合はバイパス
        proxy_cache_bypass $no_cache;
        proxy_no_cache $no_cache;

        add_header X-Cache-Status $upstream_cache_status;
    }
}

ステップ4:キャッシュの削除(purge)設定

# ✅ nginx-cache-purge モジュールを使った purge 設定
# (nginx-extras パッケージが必要)

# ✅ purge エンドポイントを内部ネットワーク限定で公開
server {
    location ~ /purge(/.+) {
        allow 127.0.0.1;
        allow 192.168.0.0/16;
        deny all;
        proxy_cache_purge MAIN_CACHE "$scheme$proxy_host$1";
    }
}
# ✅ キャッシュを手動でクリア(purge モジュールなし)
# キャッシュディレクトリを削除して再作成
sudo rm -rf /var/cache/nginx/*
sudo systemctl reload nginx

# ✅ 特定ファイルだけ削除
find /var/cache/nginx -name "*.cache" -mmin +60 -delete

# ✅ キャッシュの状態をスクリプトで確認
curl -sI https://example.com/page/ | grep "X-Cache-Status"
# → X-Cache-Status: HIT

ステップ5:キャッシュのパフォーマンスを最適化する

# ✅ stale キャッシュをバックエンドエラー時に返す
proxy_cache_use_stale error timeout updating
    http_500 http_502 http_503 http_504;

# ✅ 同じキャッシュキーへの同時リクエストを1つにまとめる(Thundering Herd 対策)
proxy_cache_lock on;
proxy_cache_lock_timeout 5s;

# ✅ バックグラウンドでキャッシュを更新(レスポンス遅延なし)
proxy_cache_background_update on;

# ✅ キャッシュ情報をログに記録
log_format cache_log '$remote_addr - $upstream_cache_status [$time_local] '
    '"$request" $status $body_bytes_sent';
access_log /var/log/nginx/cache.log cache_log;
# ✅ キャッシュヒット率を確認
sudo awk '{print $3}' /var/log/nginx/cache.log | sort | uniq -c
# →   850 HIT
# →   150 MISS
# →    30 BYPASS
# ヒット率 = 850 / (850+150+30) = 83%

注意事項

  • proxy_ignore_headers Cache-Control Expiresは強力な設定です。バックエンドが意図的にCache-Control: no-storeを返しているページ(決済ページ・マイページなど)もキャッシュされてしまう可能性があります。バイパス設定を必ず組み合わせてください
  • キャッシュディレクトリ(/var/cache/nginx/)はディスクを大量に消費する可能性があります。max_sizeを必ず設定し、定期的に使用量を監視してください

まとめ

Nginxのproxy_cacheは①curl -sIX-Cache-Statusヘッダーを確認・キャッシュファイルの状態とディスク使用量を確認、②proxy_cache_pathでゾーン定義(levels/keys_zone/max_size)・proxy_cache_validでステータス別有効期間設定・proxy_ignore_headersでCache-Control無視、③Cookieや管理ページURLで$no_cache変数を設定・proxy_cache_bypass/proxy_no_cacheでバイパス、④proxy_cache_purgeでpurge設定・rm -rfでキャッシュディレクトリ手動クリア、⑤proxy_cache_use_staleでエラー時にstale返却・proxy_cache_lockでThundering Herd対策・proxy_cache_background_updateでバックグラウンド更新の手順で設定します。

お気軽にご相談ください

お見積りへ お問い合わせへ