#はじめに
「日本からアクセスしているのに、アメリカのサーバーまでデータを取りに行くのは遅い」——CDN(Content Delivery Network)はこの問題を解決します。
CDNは世界中にエッジサーバーを配置し、ユーザーに最も近い場所からコンテンツを配信します。これにより、レイテンシーの削減とオリジンサーバーの負荷軽減を実現できます。
この記事を読むと、以下のことができるようになります:
- CDNキャッシュの仕組みを理解できる
- キャッシュパージの方法と注意点がわかる
- Varyヘッダーの役割を理解できる
#CDNとは
CDN(Content Delivery Network)とは、世界中に分散配置されたサーバー群で、ユーザーに近い場所からコンテンツを配信するネットワークです。
従来:
[日本のユーザー] --------太平洋を超えて-------- [米国のサーバー]
遅い (RTT: 150ms)
CDN利用:
[日本のユーザー] --- [東京エッジ] --- [米国のサーバー]
近い (RTT: 10ms)
#CDNキャッシュの仕組み
#エッジサーバー
CDNの各拠点に配置されたサーバーを「エッジサーバー」と呼びます。
[オリジンサーバー]
↓
┌─────────────────────┴─────────────────────┐
↓ ↓ ↓
[東京エッジ] [ロンドンエッジ] [NY エッジ]
↓ ↓ ↓
[日本ユーザー] [欧州ユーザー] [米国ユーザー]
#キャッシュフロー
1. ユーザーAがリソースをリクエスト
→ エッジにキャッシュなし
→ オリジンから取得してキャッシュに保存
→ ユーザーAにレスポンス
2. ユーザーBが同じリソースをリクエスト
→ エッジにキャッシュあり
→ オリジンへのリクエストなしでレスポンス(高速)
#オリジンへのリクエスト削減
多くのユーザーがエッジキャッシュから取得するため、オリジンサーバーへのリクエストが大幅に減少します。
CDN導入前: オリジンへ 100,000 リクエスト/日
CDN導入後: オリジンへ 1,000 リクエスト/日(99%削減)
#Cache-Controlとの関係
CDNはHTTPのCache-Controlヘッダーに従ってキャッシュ動作を決定します。
#s-maxage
共有キャッシュ(CDN)専用の有効期限です。
Cache-Control: max-age=60, s-maxage=3600
- ブラウザ: 60秒間キャッシュ
- CDN: 3600秒間キャッシュ
CDNでは長くキャッシュしてオリジンへのリクエストを減らし、ブラウザでは短くキャッシュして更新を早く反映させる、という使い分けができます。
#private
ユーザー固有のデータはCDNでキャッシュしてはいけません。
Cache-Control: private, max-age=3600
これにより、CDNはこのレスポンスをキャッシュせず、各ユーザーがオリジンから取得します。
#public
明示的に共有キャッシュでのキャッシュを許可します。
Cache-Control: public, max-age=3600
#キャッシュパージ
キャッシュパージとは、CDNにキャッシュされたコンテンツを強制的に無効化または削除することです。
#パージが必要な場面
- コンテンツを緊急で更新したい
- 誤った内容がキャッシュされた
- セキュリティ上の問題が発覚した
#パージの方法
#1. URLベースのパージ
特定のURLのキャッシュのみを削除します。
# Cloudflare API の例
curl -X POST "https://api.cloudflare.com/client/v4/zones/{zone_id}/purge_cache" \
-H "Authorization: Bearer {token}" \
-d '{"files":["https://example.com/style.css"]}'
#2. タグベースのパージ
キャッシュにタグを付けておき、タグ指定でまとめて削除します。
# オリジンのレスポンス
Cache-Tag: homepage, marketing
# パージリクエスト
{"tags": ["marketing"]} # marketingタグの全キャッシュを削除
#3. 全パージ
すべてのキャッシュを削除します。
curl -X POST ".../purge_cache" \
-d '{"purge_everything": true}'
注意: 全パージ後はオリジンへのリクエストが急増するため、慎重に実行してください。
#パージの伝播時間
パージ後、すべてのエッジサーバーに反映されるまで時間がかかることがあります(通常数秒〜数分)。
#Varyヘッダー
Varyヘッダーは、どのリクエストヘッダーに基づいてキャッシュを分離するかを指定します。
#なぜ必要か
同じURLでも、リクエストヘッダーによって異なるレスポンスを返すことがあります。
# 日本語ブラウザからのリクエスト
GET /page
Accept-Language: ja
# 英語ブラウザからのリクエスト
GET /page
Accept-Language: en
Varyがないと、日本語ユーザー向けの内容が英語ユーザーにキャッシュから配信されてしまう可能性があります。
#Varyの使用
Vary: Accept-Language
これにより、Accept-Languageヘッダーの値ごとに別のキャッシュが保持されます。
/page (Accept-Language: ja) → 日本語コンテンツ
/page (Accept-Language: en) → 英語コンテンツ
#よく使うVaryの値
| Vary | 用途 |
|---|---|
Accept-Language | 言語別コンテンツ |
Accept-Encoding | 圧縮方式別(gzip/br) |
Accept | フォーマット別(HTML/JSON) |
Cookie | ユーザー別(使用は推奨されない) |
#Vary: Cookieの問題
Vary: Cookie
Cookieはユーザーごとに異なるため、事実上キャッシュが効かなくなります。ユーザー固有のコンテンツにはCache-Control: privateを使用してください。
#CDN固有のヘッダー
多くのCDNは、独自のヘッダーで動作を制御できます。
#Cloudflare
# CDNのキャッシュTTL
CDN-Cache-Control: max-age=86400
# キャッシュタグ
Cache-Tag: blog, article-123
#Fastly
# Surrogate-Control(CDN専用のCache-Control)
Surrogate-Control: max-age=3600
# キャッシュキー
Surrogate-Key: blog article-123
#CloudFront
# TTLの制御はビヘイビア設定で行う
# または Cache-Control を使用
#CDN選定のポイント
| 観点 | 確認項目 |
|---|---|
| エッジロケーション | ターゲット地域にPoPがあるか |
| パージ速度 | 緊急更新時の反映時間 |
| キャッシュ制御 | タグ、パス、ヘッダーでの制御 |
| コスト | 帯域、リクエスト数の課金体系 |
| 機能 | WAF、画像最適化、Workers |
#主要なCDNサービス
- Cloudflare: 無料プランあり、幅広い機能
- Fastly: リアルタイムパージ、高度なVCL
- Akamai: 最大規模のネットワーク
- CloudFront: AWS連携、Lambda@Edge
- Vercel Edge: Vercelプラットフォーム統合
#まとめ
- CDNはエッジサーバーでコンテンツをキャッシュし、ユーザーに近い場所から配信
- s-maxageでCDN専用の有効期限を設定
- privateでユーザー固有データのCDNキャッシュを防止
- キャッシュパージで緊急時に更新を反映
- Varyヘッダーでリクエストヘッダーに基づくキャッシュ分離
#次のステップ
CDNキャッシュを理解したところで、次はキャッシュバスティング戦略について学びましょう。ファイル名にハッシュを含める方法など、「更新を確実に反映させつつ、最大限キャッシュする」ための実践的なテクニックを紹介します。