LIVESENSE ENGINEER BLOG

リブセンスエンジニアの活動や注目していることを発信しています

画像配信システムにCDNの導入を試みた話

こんにちは。9月よりインターンとして参加しているインフラグループの幸田です。
現在リブセンスでは、高速化の取り組みを進めており、その一環として今回は画像配信システムへのCDN導入検証を行いました。

この記事では導入検証を通して見つけた、最低限確認しておきたい キャッシュヒット率 に関わる設定を2つ紹介します。

検証の背景とか

ステージング環境での検証 というフェーズで、インターン課題として取り組みました。
最低限キャッシュを無視する設定(PASS設定)しかされておらず、まさに「とりあえず通してある」という感じです。

ここから本番環境へ導入を進めるための導入検証をはじめました。

前提とか設定とか

前提として、今回導入検証を行うのは画像の配信を専門に行う 画像配信システム です。
CDNには Fastly を使用しました。
(以下Fastlyに合わせて画像配信システムのことを Origin と表現します)

ステージング環境は社内からしかアクセスできないので、そのままだとキャッシュヒット率の計測がうまく行えません。
そのため今回検証するステージングのOriginには、本番トラフィックの1/3をミラーリングし、ある程度トラフィックを確保した状態で、動作確認や検証を行いました。
この時点でのキャッシュヒット率は平均で30%~35%程でした。

とりあえずやってみよう

「キャッシュさせて高速にコンテンツを配信する」という観点で見た時、キャッシュヒット率が低くCDNとしての役割を果たせていないと思ったので「 思い当たる設定を見てみる 」ことにしました。

まずはTTLの設定を見てみる

キャッシュの話になった時、初めに思い浮かぶ設定値といえばTTL(Time to live)ではないでしょうか。
TTLは「どのくらいの期間キャッシュとして保持するか」という設定です。

Origin側の設定ファイルを確認しましたが指定はなく、更に前提でも書いたようにFastlyで明示的な設定も施していませんでした。

TTL指定しなかったらどうなる?

Fastlyではデフォルト値としてTTLが 120s に設定されています。
OriginやFastlyで特に指定がない場合はこの数値が適用されます。

つまり2分間だけキャッシュとして保持され、期限が切れるとOriginから取得して再度2分間キャッシュするという動きになります。
そのためキャッシュヒット率低下に繋がります。

TTLを設定する

「明示的にTTLを設定しなかったために 120s が適用され、キャッシュされる時間が短かった」というのが今回の原因なので、 明示的にTTLの値を設定 してみましょう。

TTLの設定方法はいくつかありますが、今回はOriginで Surrogate-Control というヘッダを付与して設定しました。
ヘッダに関する詳しい内容はこちらを参照してください。

nginxでの設定例です。

+    add_header Surrogate-Control "max-age=604800";

Surrogate-Control は今回で言うとFastlyなど 間に入るProxyサーバにのみ有効なTTL値を設定するためのヘッダ です。

通常 Cache-Control で設定したTTLはブラウザなどにも適用されますが、 Surrogate-Control は今回の場合だと、Fastlyだけで取り扱われ、その後取り除かれます。
そのためブラウザからこのヘッダは確認できません。

今回の Surrogate-Control の値は 604800s1 にしてみました。

TTLの設定値について

今回は「検証のために、ある程度長くしてみよう」という考えから 604800s を指定しましたが、本当にこの設定値が適切なのでしょうか。

個人的には正解がないような気がしていて、扱うコンテンツによっても変わってくるものだと思います。
なのでこのあたりの設定値は、コンテンツの種類や更新頻度を総合的に判断した上で設定する必要があります。

例えば、

  • あまり更新されることがないから、(仮に、少しの間古い情報が返されたとしても)大きな問題がない場合
  • そこそこ高頻度で更新されるので、数日間保持されると困る場合

など。
「すぐに更新してくれないと困るものなのか?」や「逆にちょっとくらい遅れても困らないものなのか?」という点に着目するとより適切な設定ができるかと思います。

極端な話をすると「何ヶ月も更新されることがないのであれば、何ヶ月も保持していい」ので。

キャッシュの更新どうする?

またキャッシュの更新をTTLだけに任せると「TTLが過ぎるまではOriginでコンテンツが更新されても、キャッシュされた古いコンテンツを返すのか?」という話も出てきます。

これについては、 CacheBusting と呼ばれる手法を用いることで解決することができます。
GETパラメータで更新日時などを付け加えて別のURLにすることによって、再取得させる方法です。

それ以外にもFastlyには 強力なPurge機能 が備わっています。Purge機能とはキャッシュを削除する機能です。
Originでコンテンツを更新した時にこのAPIを叩くような実装をすると、すぐ(ミリ秒単位)にFastly上からキャッシュを削除することができます。
CacheBusting の場合だとTTLが過ぎるまではサーバ上に残ることになるので、少しだけセンシティブな内容を扱う時はPurgeするやり方がオススメです。

ん?ブラウザ変えたらHITしなくなるな?

キャッシュのHIT,MISSの洗い出しをしようと思い、主にGoogleChromeのDevToolsを眺めていました。
普段はFirefoxを使用しているのですが、DevToolsが優秀なのでこういう検証をする時にはChromeも使っています。

その過程で「Firefoxで何度も表示させていたページを、Chromeで確認するとMISSになる」という現象から、User-Agent(以下UA)を取り扱うVaryヘッダに目をつけました。

Varyヘッダを取り扱うとどうなるか

そもそもVaryヘッダは「同一のURLでもヘッダの内容が違うから、別のコンテンツとして扱ったよ。キャッシュとかするならそこらへんよろしくね」という命令にあたります。
よくある例だと、UAのデバイスの情報をもとにコンテンツの出し分けを行っている時、CDNやL7LBに別物として認識させるようなケースでしょうか。

Fastlyでは2特に指定をしない限り、Varyヘッダを取り扱います。
つまりUAなどが含まれていた場合、 UA毎にキャッシュを生成します
UAはクライアントの様々な情報を格納しているため種類が多く、キャッシュヒット率に影響します。

今回の場合だとOriginでUAが付与されていたため、まさに「UA毎にキャッシュが生成されている」という状態でした。

じゃあVaryヘッダ消そう

この問題に対する対処法はいくつかあります。

  • FastlyでVaryヘッダを削除してキャッシュする
  • OriginでVaryヘッダを適切に設定する
  • FastlyでUAを正規化する

など。

今回は1つ目の、 FastlyでVaryヘッダを削除してキャッシュする という方法を採用しました。

前提でも話したように、今回対象となるのは画像配信システムであり画像以外のコンテンツを扱っていません。
またUAを利用してのコンテンツの出し分けも行っていないため 「 Varyヘッダを扱う必要がない 」 という理由から、削除する方法を取りました。
VaryヘッダにはUA以外にも Accept-Encoding なども含まれていますが、今回の場合は不要なので削除しました。

それ以外にも「FastlyのダッシュボードからGUIで設定可能であり、素早く試せる」というのも理由の1つです。

設定

Fastlyの設定画面からGUIで設定することができます。

1.対象のダッシュボード画面を開きます。
2.[CONFIGURE]を開いて、CONFIGURATION > Clone activeをクリックします。これで現在の設定がCloneされます。
3.サイドメニューより[Content]を開き、CREATE HEADERから画像のように設定します。

効果を確認

時系列で話すと、Varyヘッダの削除→TTLの設定という順番で検証を行いました。
なので、Varyヘッダの設定を入れたのが左の赤ラインで、TTLの設定を入れたのが右の赤ラインです。
当初平均で30%程だったヒット率が今だと平均で80%近くまで上がってきています。

  • Varyヘッダの設定単体で見ると、約20%UP
  • TTLの設定単体で見ると、約25%UP

といった感じです。

おわりに

この記事では最低限チェックしたいポイントを上げましたが、他にもヒット率を上げるための方法はいくつもあると思います。
また今回は画像配信だけを行うシステムを対象にしたのであまり複雑な設定をしなくても済みましたが、他のコンテンツも扱う場合だとUAが必要になったりなど色々複雑になってきます。
特に 個人情報などセンシティブな内容が絡んでくる場合は、設定を慎重に行う必要があります。

FastlyではVCLと呼ばれる言語を利用して複雑な処理を行うこともできるので、工夫次第でもっと最適な設定ができそうですね。

おまけ:感想的な何か

2週間という短い期間でしたが、内容の濃いインターンでした。
「なんかFastly流行ってるしカッコいいからこれがいい」という理由で、インターン課題を選定しましたがCDNに対する理解がより一層深まりました。
また技術的な部分はもちろん、ドキュメントを作成する時のコツなどそれ以外のこともたくさん学べました。

インターン時は「コーヒーの伝道師」と呼ばれ、社員の方に慕われたりなどすごく楽しかったです(笑)

最終日の焼肉も美味しかったです!関わってくださった社員の皆様ありがとうございました!


  1. 604800s = 1週間
  2. デフォルトのVaryヘッダの取り扱い方については、各CDNによって異なるので注意が必要です。