CDNは「導入すると全部保存される仕組み」ではありません。保存してよい内容、キー、鮮度、再検証を順に確認します。役割の比較は親の負荷分散・プロキシ・CDN、具体的な観測と旧設定の訂正は本ページを参照してください。
| この記事の要点 |
|
概要
CDN (Content Delivery Network / コンテンツ配信ネットワーク) とは、画像・CSS・JavaScript・動画などのコンテンツを、世界各地に分散配置したエッジサーバ (キャッシュサーバ) に複製し、経路や遅延等に応じた拠点から配信する仕組みです。選択方法はサービスごとに異なり、地理的な最寄りが保証されるわけではありません。元データを持つオリジンサーバへ全アクセスを集中させる代わりに、各地のエッジが代理で配信することで、応答速度を上げ、オリジンと回線の負荷を大幅に下げます。親項目は 負荷分散・プロキシ・CDN です。
CDN は実体としては地理的に分散した巨大な リバースプロキシ + キャッシュ群と捉えると理解しやすく、近年は単なる高速化だけでなく、DDoS 緩和や WAF、TLS 終端などセキュリティ機能の提供基盤としても重要になっています。
仕組み
利用者がコンテンツを要求すると、サービス側のDNSや経路制御等で配信拠点へ誘導されます。CloudFrontは通常ネットワーク遅延を考慮したPOPへ向けます。すべてのCDNがDNSだけで地理的最寄りを選ぶという意味ではありません。エッジは次のように動作します。
- キャッシュヒット: 保存済みの応答があり、キー・鮮度・要求や応答の条件から再利用が許される場合はエッジから返せます。保存済みというだけで毎回の再利用が保証されるわけではありません。
- キャッシュミス: 応答が無ければ取得が必要です。期限切れは条件付き要求で再検証し304で既存本文を使える場合や、許可されたstale応答を返せる場合もあり、常に本文の全量取得ではありません。保存禁止・退避/eviction・別拠点・異なるキー等で次回もヒットしない場合があります。
キャッシュをどれだけの期間有効とみなすかは TTL (Time To Live) で決まり、オリジンが返す Cache-Control: max-age=... ヘッダなどで制御します。頻繁に変わらない静的ファイルは長めの TTL、頻繁に更新されるものは短め、ユーザ個別の動的コンテンツはそもそもキャッシュしない (Cache-Control: no-store)、という使い分けが基本です。HTTP ヘッダの基礎は HTTP を参照してください。
地理的に分散したエッジは、世界中からのアクセスをそれぞれの拠点で受け止めるため、結果として地理分散による負荷分散と、後述の DDoS 緩和を同時に実現します。
設定・実用例
次の旧例の訂正:max-age=60, must-revalidateは「毎回再検証」ではなく、通常は60秒の鮮度を失った後に有効な再検証なしで再利用しない指定です。静的ファイルすべてに1年を指定するのではなく、内容に応じて名前を変える公開ファイルだけへ限定します。no-storeは既に保存された古い応答の削除指示ではありません。旧例をそのまま全サイトへ適用しません。
# nginx: 拡張子別にキャッシュ制御を出し分ける
location ~* \.(?:css|js|png|jpg|jpeg|gif|woff2)$ {
# 静的アセットは長期キャッシュ (1 年, 変更時はファイル名を変える)
add_header Cache-Control "public, max-age=31536000, immutable";
}
location = /index.html {
# HTML は短時間、毎回オリジンで再検証
add_header Cache-Control "public, max-age=60, must-revalidate";
}
location /api/ {
# 動的・個人向けはキャッシュさせない
add_header Cache-Control "no-store";
}
旧HEAD例の確認範囲:各サービスの応答ヘッダーは観測の手掛かりですが、HEADとGETで処理が違う場合があり、1回のHITだけで全拠点のヒット率・鮮度・性能を証明できません。URLのqueryやCookie、応答のSet-Cookie等に秘密値を含めず、出力を共有する前に伏せてください。
# 応答ヘッダを確認 (Cache-Control や CDN のヒット表示を見る)
curl -I https://www.example.com/assets/app.css
# 例) 出力に含まれるヘッダ
# cache-control: public, max-age=31536000, immutable
# cf-cache-status: HIT (Cloudflare の場合)
# x-cache: Hit from cloudfront (CloudFront の場合)
# コンテンツ更新時はキャッシュをパージ (各 CDN の API/管理画面で実施)
# 例: ファイル名にハッシュを付けてキャッシュバスティングするのが定石
# app.css -> app.4f8a2c.css
保存・鮮度・再検証を分ける
| 指定 | 意味と確認点 |
|---|---|
| public / private | publicは共有キャッシュでの保存を許す指定、privateは共有キャッシュには保存させない指定。privateだけでブラウザの保存も禁止するわけではありません。 |
| no-store | その要求/応答を保存しない指示。過去に保存された別の応答を遡ってすべて削除する指示ではありません。 |
| no-cache | 保存禁止ではなく、通常は利用前の再検証が必要です。名前だけでno-storeと同じにしません。 |
| max-age / s-maxage | 鮮度の期間を制御します。共有キャッシュ向けのs-maxageとブラウザにも関係するmax-ageを区別し、Age等も見ます。 |
| must-revalidate | staleになった応答は成功した再検証なしに再利用できません。max-age=60と組み合わせても毎回の問い合わせ指定ではありません。 |
ETagやLast-Modifiedを使った条件付き要求に304が返れば、保存済み本文の再利用ができます。逆に保存されていても、要求のno-cache・別キー・サービス独自ルール等でオリジン確認が必要になる場合があります。stale-while-revalidate等は許可された条件で使う別の方針であり、must-revalidateを無視してよいという意味ではありません。
共有してよい範囲とキーを先に決める
ログイン・権限・言語・Cookie・query等で本文が違う要求を同じキーへまとめると誤配信します。個人情報を含むページは、明示した保存方針とCDN側ルールを確認して共有キャッシュを避けます。キーへ不要なパラメーターを無差別に含める方法も、ヒット率を落とすだけで正確性を保証しません。
Cloudflareの標準ではHTML/JSONをキャッシュしませんが、ルール等で変わります。Cache-Control・Set-Cookie・認証等の扱いと、設定したサービス/プランの例外を確認します。他CDNに同じ既定値を当てはめません。no-storeを追加しただけで既存の誤配信が止まるとは判断せず、必要なら対象を特定した無効化とアクセス制御を事故対応として行います。
検証用のnginx断片
以下はhttpブロック内に置く、loopback限定の静的検体です。/assets/には内容ごとに名前を変える公開ファイルだけを置きます。実アプリの認証・proxy_pass・全URLに対するルーティングを構成するものではありません。APIのno-storeをalways付きにしてエラー応答も観測しますが、これだけで実CDNのルールが正しくなるわけではありません。
# Inside http {}; static fixtures only, not an application deployment config.
server {
listen 127.0.0.1:18081;
server_name localhost;
root /fixture/www;
location /assets/ {
# Only public, content-addressed files belong in this directory.
try_files $uri =404;
add_header Cache-Control "public, max-age=31536000, immutable";
}
location = /index.html {
add_header Cache-Control "public, max-age=60, must-revalidate";
}
location /api/ {
add_header Cache-Control "no-store" always;
}
}
観測と変更を混ぜない
同じ公開テストURLを、同じmethod・Cookie/query・地域条件で比較します。以下のURLは説明用なので、許可された公開リソースに置き換えます。GETの応答ヘッダーを読みますが、Set-CookieやURLの秘密値を共有しないでください。認証ページを大量に取得したり、確認のため全キャッシュを削除したりしません。
# Public diagnostic URL only; headers can include cookies/private identifiers.
# Replace this illustrative URL with an authorized, non-personal test resource.
curl --silent --show-error --max-time 15 \
--dump-header - --output /dev/null \
https://www.example.com/assets/app.4f8a2c.css
- 要求URL・method・時刻・応答statusを記録し、どの層が応答したかを調べる。
- Cache-Control / Age / Vary / ETag / Last-Modifiedとサービス固有の状態ヘッダーを読む。
- ブラウザ・CDN・リバースプロキシ・アプリ/オリジンのどこが古い本文を返すかを分ける。オリジンへの確認も許可された経路だけで行う。
- 変更前に、対象キー・TTL・パージの範囲と、既に公開したimmutableファイルのURL変更方針を決める。
- 変更後は共通ファイルと個人別応答の両方を確認する。1回のHITを全利用者の速度改善や情報漏えい防止の証明としない。
主な用途
- 静的コンテンツ配信: 画像・CSS・JS・フォントなどをエッジから高速配信し、表示を速くする。
- 動画・大容量配信: 動画ストリーミングやソフトウェア配布を地理分散で効率配信する。
- オリジン負荷軽減: アクセスの大半をエッジで吸収し、オリジンサーバの負荷とコストを下げる。
- DDoS 緩和: 大量の攻撃トラフィックを世界中のエッジで分散吸収し、オリジンを守る。
- セキュリティ前段: TLS 終端・WAF・ボット対策をエッジで提供し、不正アクセスをオリジン手前で遮断する。
主要 CDN サービスの比較
| サービス | 提供元 | 特徴 |
|---|---|---|
| Cloudflare | Cloudflare | キャッシュ/DNS/保護機能をプラン・有効設定ごとに確認 |
| Amazon CloudFront | AWS | AWS 各サービスとの統合が強力 |
| Fastly | Fastly | キャッシュ制御・パージ機能。反映条件と対象範囲を確認 |
注意点
- キャッシュの鮮度管理: TTL を長くしすぎると更新が反映されない。コンテンツ更新時はパージするか、ファイル名にハッシュを付けるキャッシュバスティングを行う。
- 動的コンテンツの誤キャッシュ: ログイン後のページや個人情報を誤ってキャッシュすると、他人に表示される重大事故になる。
Cache-Control: no-storeやキャッシュキー設計に注意する。 - オリジンの保護: オリジンの IP が漏れると CDN を迂回して直接攻撃される。CDNからの経路制限や認証/TLS、直接アクセス時の制御を設計する。IPを秘密にするだけ、または共有CDNの送信元IPを許可するだけでサイト固有の認証が完了するとは扱わない。
- キャッシュキーと応答の正しさ: Cookie やクエリ文字列をキーに含めるかで、ヒット率と正しさが変わる。応答が違う要求を同じキーへまとめると誤配信、不要に分けるとヒット率低下が起こり得ます。
- 地域差・障害: エッジの拠点が無い地域では効果が薄い。また CDN 自体の障害が広域影響を及ぼすため、フェイルオーバー方針も考える。
関連リンク
公式資料と確認範囲
2026年10月26日確認:HTTPキャッシュ仕様(RFC 9111)、Cloudflareの標準キャッシュ・再検証、CloudFrontの配信拠点/キャッシュ、nginxの応答ヘッダー。追加nginx例はHTTP応答の検査用であり、実CDNの全拠点/プラン・課金・パージ・キャッシュキー・WAF・性能を検証するものではありません。CWiki本番のキャッシュ/広告設定は変更していません。
子ページはありません
人気ページ
- 1 Eclipseで「サーバーに追加または除去できるリソースがありません。」の原因と対処法
- 2 tomcat の起動 / 停止ログと catalina.log・catalina.out の違い
- 3 JavaScript で base URL を取得する方法|window.location.origin
- 4 YouTube Data API v3 エラー一覧|403・400・404 の原因と対処
- 5 Laravel エラー一覧|500/Blade/DB 接続/ルーティングの代表エラー
- 6 3Dグラフィックスのソフト一覧|Blender・Metasequoiaと用途別の選び方
- 7 Spring Frameworkのアノテーション一覧
- 8 【Spring】@Valueアノテーションとは
- 9 CATALINA_HOME の確認方法 (Linux / Mac)
- 10 【Spring】@Autowiredアノテーションとは
最近更新/作成されたページ
- Visual Studio「デザイナーを表示できません」エラーの原因と対処 2026-10-28 12:06:00
- SSH 認証に失敗しました。再試行してください の対処 2026-10-28 12:06:00
- SSH2 秘密鍵の読み込みに失敗しました の原因と対処 2026-10-28 12:06:00
- TeraTerm のよくあるエラーと対処法完全ガイド — Connection refused / 2026-10-28 12:06:00
- Visual Studio エラー一覧|コンパイルエラー・警告の確認方法と対処 2026-10-28 11:39:57
- Whitelabel Error Page の原因と消し方|Spring Boot のエラーページ 2026-10-28 11:39:57
- Eclipseで「サーバーに追加または除去できるリソースがありません。」の原因と対処法 2026-10-28 11:39:57
- SQL WHERE 句完全ガイド 2026-10-28 11:39:57
- SQL JOIN 完全ガイド (INNER/LEFT/RIGHT/FULL OUTER) 2026-10-28 11:39:57
- tomcat の起動 / 停止ログと catalina.log・catalina.out の違い 2026-10-28 10:24:23
- Tomcat の起動確認方法 5 つ|localhost:8080・ポート・プロセス・ログ 2026-10-28 10:24:23
- Oracle 19c COMMITの使い方: 暗黙コミット・自動確定・応答不明時の確認 2026-10-28 09:59:09
- Oracle 19c DELETE文|削除対象の確認・COMMIT前の判断・ROLLBACKの条件 2026-10-28 09:59:09
- Oracle 19c INSERT文|INSERT ALL・SELECT・RETURNINGとMERGEの使い分け 2026-10-28 09:59:09
- Oracle 19cのトランザクション制御|COMMIT・ROLLBACK・分離レベルと接続設定 2026-10-28 09:59:09