Cloud CDNでCache-Controlを使ってキャッシュ制御したい(Google Cloud)
はじめに
システムソリューション部所属、インフラに少々携わっておりますsumiです。
本日は アプリケーション ロードバランサ を使用したサーバーで、Cloud CDN を指定したファイルのみキャッシュするように設定する方法をご紹介いたします。
Cloud CDN 自体はコンテンツをエッジサーバーにキャッシュすることでサーバー負荷の軽減、レスポンスタイムのチューニング等に役立ちます。
本記事では、特定の静的コンテンツをキャッシュしないように、HTTPヘッダーでのキャッシュ制御を目的とした設定例を紹介します。
キャッシュされても困らないサイトの場合は、Google Cloud が推奨する設定「静的コンテンツをキャッシュする」、または、公式ドキュメント「キャッシュに保存されたコンテンツを無効にする」を合わせて参照してください。
※調整に当たっては、検証等行った上で実施することを強く推奨いたします。
Cloud CDN キャッシュの制御パラメータ説明
キャッシュモード
Cloud CDNは、コンテンツをどのようにキャッシュするかを制御する3つのキャッシュモードを提供しています。より詳しい説明は公式ドキュメントのリンクを記載しておりますのでそちらをご参照ください。
- CACHE_ALL_STATIC:すべての静的コンテンツ(HTML、CSS、JavaScript、画像など)をキャッシュします。
- USE_ORIGIN_HEADERS:
Content-Type
ヘッダーで指定された拡張子を持つ静的コンテンツのみをキャッシュします。 - FORCE_CACHE_ALL:
Cache-Control
ヘッダーに基づいてコンテンツをキャッシュします。
キャッシュ期間
キャッシュ期間は、キャッシュされたコンテンツが有効である期間を指定します。
- CACHE_ALL_STATIC /USE_ORIGIN_HEADERS モード:
- クライアントTTL:ブラウザやクライアントにキャッシュを保持させる期間を指定します。
- デフォルトTTL:オリジンサーバーからのレスポンスに
Cache-Control
ヘッダーがない場合に適用されるキャッシュ期間を指定します。 - 最大TTL:キャッシュされたコンテンツの最大保持期間を指定します。
- DYNAMIC_CACHE モード:
- オリジンサーバーからのレスポンスに含まれる
Cache-Control
ヘッダーのmax-age
ディレクティブでキャッシュ期間を指定します。
- オリジンサーバーからのレスポンスに含まれる
例: Cache-Control: max-age=3600 (1時間)
キャッシュキー
Cloud CDNでは、URL全体がキャッシュキーとして利用されます。
リクエストを受け取る際にプロトコル(HTTP/HTTPS)、ホスト名、クエリ文字列、HTTPヘッダー、Cookieで識別します。
プロトコル
リクエストがHTTPかHTTPSかを識別します。
デフォルト:有効
設定 | 挙動 | ユースケース |
---|---|---|
有効にする | HTTPとHTTPSのリクエストを個別にキャッシュ | HTTPとHTTPSで異なるコンテンツを提供する場合 |
無効にする | HTTPとHTTPSのリクエストを区別しない | HTTPとHTTPSで同じコンテンツを提供する場合 |
Cloud CDNの使用時には、同じホスト名でHTTPとHTTPSのコンテンツを配信するのが一般的ですが、
特定のブラウザがTLSを必須とするため、異なる配信を許可するユースケースも存在します。詳細はこちらをご参照ください。
HTTP/HTTPSで同一ホスト名を使用する
ホスト
複数のホスト名で異なるコンテンツを配信する際に利用します。
デフォルト:有効
クエリ文字列
URLの「?」以降に続くパラメータを識別します。
デフォルト:有効・選択項目以外をすべて含める・値無し
設定 | 挙動 | ユースケース |
---|---|---|
選択項目のみを含める | キャッシュキーに指定のパラメータを含める | 検索結果や商品詳細ページなど、特定のパラメータでコンテンツが変わる場合 |
選択項目以外をすべて含める | キャッシュキーに特定のパラメータを除外して他のパラメータを含める | 複数のパラメータが存在するが一部のみをキャッシュキーにしたい場合 |
無効 | パラメータを用いて識別しない | クエリに依存せず、同一のコンテンツを提供する場合 |
クエリ文字列のカスタム設定では、有効にする場合にホワイトリストまたは除外リストの形式でパラメータを指定できます。
HTTPヘッダー
リクエストに含まれる追加情報を識別します。
デフォルト:無効
設定 | ユースケース |
---|---|
含める | User-AgentなどのHTTPヘッダーでコンテンツを最適化する場合 |
除外する | ヘッダーに関係なく同じコンテンツを提供する場合 |
名前付きCookie
特定のユーザーを識別するためのCookieを利用します。
デフォルト:無効
設定 | ユースケース |
---|---|
有効 | ログイン状態やユーザーによってコンテンツが変わる場合 |
無効 | Cookieに関係なく同じコンテンツを提供する場合 |
各パラメータのユースケース
ユースケース | プロトコル | ホスト | クエリ文字列 | HTTP ヘッダー | 名前付き Cookie |
---|---|---|---|---|---|
同じコンテンツを HTTP/HTTPS で配信する場合 | 除外 | 含める | 除外 | 除外 | 除外 |
複数のホスト名で同じコンテンツを配信する場合 | 含める | 除外 | 除外 | 除外 | 除外 |
クエリ文字列によってコンテンツが変わらない場合 | 含める | 含める | 除外 | 除外 | 除外 |
ユーザーエージェントごとにコンテンツを最適化する場合 | 含める | 含める | 含める | User-Agent | 除外 |
ログイン状態によってコンテンツが変わる場合 | 含める | 含める | 含める | 除外 | session_id |
DYNAMIC_CACHEモードの使い方
DYNAMIC_CACHEモードを使用するためには、サーバー側でCache-Controlを設定する方法があります。
Cache-Control ヘッダーは、HTTP レスポンスヘッダーの一つであり、ブラウザやキャッシュサーバーにコンテンツをどのようにキャッシュするかを指示するために使用されます。
このヘッダーには、以下のディレクティブを指定できます。
max-age:キャッシュの有効期限を秒数で指定します。
s-maxage:共有キャッシュ(CDN など)でのキャッシュの有効期限を秒数で指定します。
public:オブジェクトを公開キャッシュに保存できるようにします。
private:オブジェクトをプライベートキャッシュにのみ保存できるようにします。
no-cache:オブジェクトをキャッシュに保存しないようにします。
no-store:オブジェクトをキャッシュにも保存せず、ブラウザにも保存しないようにします。
実際の設定方法
環境(Rocky Linux9 + Nginx)
今回は簡単テスト環境として、Rocky Linux9 + Nginxを使用します。※サーバー構築の部分は省いております。Cacheのヒット条件のみのテストですので、Wordpress等のCMSは使用しません。
サーバ側での準備
ディレクトリ毎にキャッシュ制御を行います。
テストファイルを配置するディレクトリを作成します
mkdir -p /(ドキュメントルートのパス)/cache mkdir -p /(ドキュメントルートのパス)/nocache
テストファイルを各ディレクトリに配置します。
touch /(ドキュメントルートのパス)/cache/test.html touch /(ドキュメントルートのパス)/nocache.html touch /(ドキュメントルートのパス)/nocache/nocache.html
NginxのConf内に以下設定を追記します。
server { listen 80; # HTTP ポート (80番) でListenさせます server_name example.com www.example.com; # 運用するドメイン名() root /var/www/example.com/public_html/; # ドキュメントルート (ウェブサイトのファイルがある場所) index index.html index.htm; # デフォルトで表示するファイル location / { try_files $uri $uri/ =404; # ファイルが存在しない場合は 404 エラーを返す } location / { add_header Cache-Control "private"; # その他のリクエストは private } location /cache/ { add_header Cache-Control "public, max-age=3600"; # 1時間のキャッシュ #add_header X-Cache-Status $upstream_cache_status; #を外すことで、キャッシュがヒットしたかどうかをヘッダーに出してくれます。 #同じヘッダーをCDN側で返すことが可能のため、今回はCDN側で設定します。 } location /nocache/ { add_header Cache-Control "no-cache"; # キャッシュ無効 #add_header X-Cache-Status $upstream_cache_status; #を外すことで、キャッシュがヒットしたかどうかをヘッダーに出してくれます。 #同じヘッダーをCDN側で返すことが可能のため、今回はCDN側で設定します。 } }
設定完了後にシンタックスチェックを行いNginxを再起動しましょう。
nginx -t
以下の様な文言が出てればシンタックスにはエラーがないことになります。
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful
問題がなければNginxを再起動
systemctl restart nginx
ヘッダー確認
設定反映後、実際にテストサイトを確認して、ディレクトリ毎にCache-Controlヘッダーが付与されていることを確認しましょう。
DNSに登録していない場合には、サーバーのIPをHostsに登録し、Chromeブラウザ等のデバックツール(F12)を使用しヘッダーを確認してみましょう。
パス毎のCache-Controlは以下の様になっているはずです。
/cache/test.html
⇒Cache-Control public, max-age=3600 キャッシュがされ、なおかつ1時間保持する
/nocache/nocache.html
⇒Cache-Control no-cache キャッシュされず、常にオリジンサーバーから取得されます。
/nocache.html
⇒Cache-Control private private として扱われ、ブラウザキャッシュのみが許可されます。
Cloud CDN側での設定
キャッシュモード
⇒Cache-Control ヘッダーに基づいて送信元の設定を使用する
キャッシュキー
⇒デフォルト
パスやより詳しい設定を行う場合はキャッシュキーをカスタムにすることで編集可能となります。
カスタムレスポンスヘッダー
⇒ヘッダー名:cdn_cache_status
⇒ヘッダーの値1:{cdn_cache_status}
キャッシュのhitとmissがヘッダーに追加されるため、キャッシュ状態の確認デバックツール等からできるようになります。
設定は以上で終わりです。
完了をクリックすればすぐに保存されます。
キャッシュの状態を確認
ブラウザのシークレットウィンドウ等を開いてもう一度各パスを確認する。
※ブラウザキャッシュ等でレスポンスヘッダーが見えない場合もあります。場合によってはブラウザを変えてアクセスしてみてください。
/cache/test.html
⇒Cache-Control public, max-age=3600 #キャッシュがされ、なおかつ1時間保持する ⇒cdn_cache_status : hit #一回目のアクセスだとキャッシュがない状態となりますので、missとなります。別窓でもう一度同じサイトを開けばhitとなります。
/nocache/nocache.html
⇒Cache-Control no-cache #キャッシュされず、常にオリジンサーバーから取得されます。 ⇒cdn_cache_status : miss #キャッシュはされないのでmissとなる。
/nocache.html
⇒Cache-Control private #private として扱われ、ブラウザキャッシュのみが許可されます。 ⇒cdn_cache_status : miss #CDN側ではキャッシュはされないため、missとなる。
何度かCacheのhitを確認した後、GCPでCLB>CDN>オリジンの名前をクリック>モニタリングでCloud CDNを見ると、ヒット率がコンソール上から確認できます。
ヒット率と帯域幅を見ながら、キャッシュをより細かく設定することで、キャッシュの影響範囲を大まかに判断できますので、条件に合わせてキャッシュ範囲を調整してください。
まとめ
Cache-Control ヘッダーと Cloud CDN を使用することで、静的コンテンツをきめ細かく制御することができます。
また、コンテンツ配信を高速化し、オリジンサーバーへの負荷を軽減します。
このブログ記事が、Cloud CDN でのキャッシュ活用に役立てれば幸いです。
ビヨンドではCDN構築から運用保守サービスも行っておりますので、
CDNに関連するお問い合わせでも気軽にお問合せください!
https://beyondjapan.com/service/cdn/