CDN が速度を上げる方法 — キャッシュヒットから動的コンテンツまで
CDN が何かを一般の人の言葉ではキャッシュ・CDN の入門編で扱いました。この記事は同じテーマの実務者向けの角度です。CDN が正確にどの時間を削ってくれるのか、ヒット率は何が決めるのか、そして設定ミスがどうやって CDN を飾り物にしてしまうのかまで扱います。
CDN が削る時間 — 結局は距離です #
ネットワークの記事の結論をもう一度使います。小さいリクエストの体感速度は RTT × 往復回数で、RTT の下限は物理的な距離です。ソウルのユーザーが米国のサーバーのコンテンツを受け取ると、往復ごとに 130ms 台のコストが掛かります。CDN はこの距離を縮めます。世界中に置かれたエッジサーバーがコンテンツの写しを持っていて近い場所から応答すれば、同じリクエストの RTT が数ミリ秒台まで下がります。
効果は往復回数の分だけ掛け算されます。TCP・TLS のハンドシェイクの 2 往復 + リクエストの 1 往復が全部短い距離で起きるので、最初のバイトまでの時間(TTFB)が丸ごと下がります。オリジン(元のサーバー)の立場では、トラフィックがエッジで吸収されるので、負荷と転送費用が一緒に減る副次効果もあります。
ヒット率 — CDN の性能はこの数字一つです #
エッジに写しがあれば(ヒット)数ミリ秒、なければ(ミス)オリジンまで往復する元の時間 + 少しのオーバーヘッドです。つまり CDN の実効性能はヒット率が決めます。 ヒット率 95% と 60% は別物です。ヒット率を決める要素は二つです。
第一に、キャッシュポリシー — サーバーがヘッダーで宣言します。 CDN は基本的にオリジンの Cache-Control ヘッダーに従います。
# ビルドハッシュ付きの静的アセット — 1 年キャッシュ、不変の宣言
Cache-Control: public, max-age=31536000, immutable
# HTML — エッジには短く、ブラウザには常に再検証
Cache-Control: public, max-age=0, s-maxage=60
# パーソナライズされた応答 — 共有キャッシュの禁止
Cache-Control: private, no-store典型的な戦略が上の 3 行に全部入っています。ファイル名にハッシュが付くアセットは永遠にキャッシュしても安全で(内容が変わればファイル名が変わるので)、HTML は短いエッジキャッシュ(s-maxage)でオリジンを守りながら更新を速くし、パーソナライズされた応答は共有キャッシュに置きません。ヘッダーを宣言しなければ、CDN のデフォルトに運命を預けることになります。
第二に、キャッシュキー — 何を「同じリクエスト」と見なすか? エッジはキャッシュキー(基本的に URL)が同じでないと写しを再利用しません。ここにヒット率を削る間違いが出てきます。
- 不要なクエリパラメータ — トラッキングのパラメータ(utm_* など)が付くと、同じコンテンツが URL ごとに別の項目としてキャッシュされます。キャッシュキーから無関係なパラメータを除外する設定が処方です。
- 過剰な Vary ヘッダー —
Vary: Cookieのような宣言は事実上キャッシュを切ります。ユーザーごとにクッキーが違うからです。 - セッションクッキーがすべての応答に — 静的アセットの応答にまで Set-Cookie が付くと、キャッシュしない設定の CDN が多くあります。アセットはクッキーのないドメイン・パスに分けるのが古典的な処方です。
無効化 — キャッシュの唯一の難所 #
「長くキャッシュすると更新が遅れ、短くすると効果がない」という緊張の解き方は、コンテンツの種類ごとに違います。ハッシュ付きのアセットは無効化が要らず(新しいファイル名 = 新しいキャッシュ)、HTML・API のように URL が固定のものは短い s-maxage + デプロイ時のパージ(purge)で扱います。最近の CDN が対応する stale-while-revalidate(期限切れの写しを一旦返して裏で更新)は、短いキャッシュのミスの費用を消してくれる現実的な折衷案です。タグベースのパージ(特定の記事に関わる URL だけ選んで無効化)まで行けば、API の応答もキャッシュの対象になります。
注意すべきなのは「全体パージ」をデプロイのルーティンに入れる習慣です。デプロイのたびにヒット率が 0 から再出発し、オリジンがデプロイ直後のたびにトラフィックを丸ごと受けます。無効化は狭く、アセットはハッシュで — この二つの原則があれば、全体パージが必要なケースはまれです。
キャッシュできないもの — それでも CDN が助ける部分 #
ログイン済みユーザーの API 応答のようにキャッシュできないトラフィックでも、CDN 経由が得なケースは多いのです。理由はまた往復です。
- TLS の終端がエッジで — ユーザーとのハンドシェイクの往復が短い距離で終わります。
- エッジ〜オリジン区間の最適化 — CDN はオリジンとのコネクションを事前に温めて再利用し、事業者のバックボーンでルーティングします。ユーザーがインターネットを丸ごと渡るより速いケースも少なくありません。
- 圧縮とプロトコル — 最新のプロトコル(HTTP/2・HTTP/3)と圧縮(brotli)をエッジで処理して、オリジンが旧式でもユーザー側の体験を引き上げます。
つまり CDN は「静的ファイルの配布ツール」ではなく「ユーザーとの往復をエッジへ引き寄せる層」と見るのが、実務の感覚に合います。
まとめ #
- CDN の効果は距離を縮めて RTT × 往復回数の掛け算を減らすことです。TTFB とオリジンの負荷・転送費用が一緒に下がります。
- 実効性能はヒット率が決め、ヒット率は Cache-Control の宣言とキャッシュキーの設計が決めます。ヒット率の指標をダッシュボードに載せるのが始まりです。
- ハッシュ付きアセットは永久キャッシュ、HTML・API は短い s-maxage + 狭いパージ、パーソナライズされた応答は private が基本戦略です。
- トラッキングのパラメータ、Vary: Cookie、アセットに付くセッションクッキーが、ヒット率を削る三大ミスです。
- キャッシュできないトラフィックも、TLS の終端・コネクションの再利用・最新プロトコルのおかげで CDN 経由が得なケースが多くあります。