CDNを用いたWebアプリケーションの画像のキャッシュについて

最近、CDNを用いたWebアプリケーションにおけるデータの持ち方やCDN等の画像ファイルのキャッシュの設定に関して、どのようにすると最適になるかな、と悩む機会がありました。そして、データの設計やCDN、オリジンサーバー等のキャッシュの設定は多岐に渡り、どこから検討を始めていくとスムーズなのか、と思うに至りました。

その中で、実現したいアプリケーションの要件に対して、まず以下の2つの観点を考えると大まかに検討項目を分けられ、設計がうまくいくんじゃないかという気づきがあったので、共有してみたいと思います。

  • TTL(画像の保存期間) >0にするか、TTL=0にするか
  • データストアに保存される画像ファイルパスを変更可にするか、変更不可にするか

構成図

以下の図のように

  • 画像ファイルはオリジンサーバーにホスティングされる
  • オリジンサーバー上の画像ファイルのパスはRDS等のデータストアに保存される

という構成のWebアプリケーションを想定しています。

f:id:moritamorie:20201004194529p:plain

考えるべき観点

アプリケーションの要件として、主に画像ファイルの更新が必要なのか、不要なのかという点を元に以下の2つの観点を検討しました。

観点1: TTL(画像の保存期間) >0にするか、TTL=0にするか

  • TTL>0の場合
    • ローカルキャッシュの制御には、HTTP header(Cache-Control max-age or Expires)が設定される。
    • CDNキャッシュサーバ及びローカルに画像を保存するが、TTLが過ぎるまではキャッシュされたコンテンツを利用する。
  • TTL=0 の場合
    • ローカルキャッシュの制御には、HTTP header(Etag, Last-Modified)が設定される。
    • CDNキャッシュサーバ及びローカルに画像を保存するが、毎回画像の更新を確認し、もし変更があればコンテンツをダウンロードする。
      • もし、更新がなければ、304(not modified)が返り、Bodyは返らない。

CDNは主に以下の目的で導入されることが多いので、no-cache (キャッシュしない)という選択肢はあまり考慮しなくて良いと思っています。 no-cache は通信の最適化を目的にするには良い選択肢だと認識しています。

  • オリジンサーバへの負荷を下げること
  • クライアントへのレスポンスを早くすること

観点2: データストアに保存される画像ファイルパスを変更可にするか、変更不可にするか

  • 変更可能にする場合
    • 画像ファイルの変更時に、新しくオリジンサーバに画像を保存する
  • 変更不可にする場合
    • オリジンサーバに保存する画像自体を更新する。データストアに保存されているデータはそのままで、画像のファイル名は変更しない。
    • または、画像の更新が必要な場合には、データストアに新規にレコードを追加し、新しくオリジンサーバーに画像を保存する。

要件毎の観点の検討

①画像ファイルの更新が必要ない場合

f:id:moritamorie:20201004230841p:plain

観点1: TTL(画像の保存期間) >0にするか、TTL=0にするか

不要なコンテンツダウンロードを避けるために、基本的に一度ダウンロードしたらキャッシュを使うようにしたいので、TTL>0にする。

観点2: データストアに保存される画像ファイルパスを変更可にするか、変更不可にするか

更新がないので、変更不可にする。

懸念点・検討事項

以下の詳細な設定は、要件毎に異なるので検討する。

  • TTLはどの程度にするか。更新はないので、基本的に高いヒット率になるように設定して良い。
  • Cache-Control: max-ageではなく、s-maxageを使ったり、minimum TTL、maximum TTLを使う。
    • 例えばAkamaiだと使えないオプションになるので、利用するCDN毎にどの程度要件に合わせられるか変わってくる。
  • Cache-Controlヘッダー等の設定は、CDN側で設定するか、オリジンサーバー側で設定するか。

②画像ファイルの更新があり、かつオリジンサーバへのリクエストに制約がない場合

f:id:moritamorie:20201004231646p:plain

この選択肢は、一度保存した画像ファイルのパスは変更せずに、コンテンツのみ変える必要があるケースで有効だと思いました。

  • オリジンサーバへの負荷が高くなり、リクエスト数も増える
    • オリジンサーバーに、S3のようにGETが5,500回という制約があるようなサービスを利用する場合には、要件を元に採用可否を検討。(参考
  • クライアントへのレスポンスが遅くなる
    • 即時性が求められる要件には向かない。
  • 画像ファイルは、遅延なく常に最新のコンテンツを利用したい

という特徴があります。

観点1: TTL(画像の保存期間) >0にするか、TTL=0にするか

TTL=0 にし、都度画像ファイルの更新有無をオリジンサーバに確認する。

観点2: データストアに保存される画像ファイルパスを変更可にするか、変更不可にするか

データストアの画像ファイル名は変更不可にする。画像ファイルパスはそのままで、コンテンツのみを更新する。

懸念点・検討事項

以下の点は要件に応じて検討が必要。

  • 大体のCDNは従量制なので、TTL=0にして、コンテンツのダウンロードが多くなった場合、費用負担が大きくならないか。
  • 画像ファイルの更新頻度が高いケースにおいては、CDNのキャッシュの効果が薄くなる。
    • この場合は、CDNの利用をやめる、
    • もしくは、通信の最適化の目的のみでCDNを利用する。

③画像ファイルの更新があり、かつオリジンサーバへのリクエストに制約がある場合

f:id:moritamorie:20201004232522p:plain

この選択肢は、一度保存した画像ファイルのパスは変更して、既にホスティングされている画像ファイルコンテンツ自体の内容は変えないケースで有効だと思いました。

②の逆で

  • オリジンサーバへの負荷は低く、リクエストを少なくしたい
  • オリジンサーバーにリクエストの制約があるようなサービス
  • クライアントへのレスポンスに即時性を求める

というケースで有効です。

観点1: TTL(画像の保存期間) >0にするか、TTL=0にするか

一度保存された画像は同じパスのまま更新されることはないので、①と同じでTTL(画像の保存期間) >0で良い。懸念点・検討事項も同様。

観点2: データストアに保存される画像ファイルパスを変更可にするか、変更不可にするか

データストアに保存される画像ファイルパスを変更可にし、オリジンサーバーに保存されている画像自体を更新するというよりは、新しいパスで画像のファイルを保存する。

懸念点・検討事項

この選択肢の懸念点は

  • データストアの画像ファイル名を変更することになるので、データ自体をKVSに一時的に保存しているような場合には、RDSとの同期性の検討が必要。
    • 同期しない時間が長く、支障がある場合はデータストアにレコードを追加する。
  • 変更前のパスの画像ファイル、データストアのレコードをどのタイミングで削除するか。
  • 画像ファイルの更新頻度が高いケースにおいては、CDNのキャッシュの効果が薄くなる。
    • この場合は、CDNの利用をやめる、
    • もしくは、通信の最適化の目的のみでCDNを利用する。

参考資料