2013-03-18

CloudFlareの3種類のキャッシュレベルの違いを調べた

【この記事の概要】

前回⇒ CloudFlareでキャッシュ可否の条件は「URLの末尾がキャッシュ対象拡張子に見えること」だった

CloudFlareのキャッシュレベルは Basic / Simplified / Aggressive の3段階から選べますが、その違いがイマイチ解らなかったので調べました。


3段階のキャッシュレベルの違いは?

CloudFlareの「パフォーマンス設定」画面では、Caching Levelを下記3段階に設定できるとあります。
  • Aggressive: http://cloudflare.example.jp/pic.jpg?with=query
  • Simplified: http://cloudflare.example.jp/pic.jpg?ignore=this-query-string
  • Basic: http://cloudflare.example.jp/pic.jpg
言わんとすることはだいたい分かるんですが、具体的な挙動を見てみました。

BasicSimplifiedAggressive
(1) test.js○される○される○される
(2) js.cgi?q=.js○される○される○される
(3) test.html×されない×されない×されない
(4) js.cgi?1=.js&2=query×されない×されない×されない
(5) test.js?with=query×されない△されるけど※1○されるけど※2

(1)や(2)のように、URLがキャッシュ対象拡張子で終わっている(ようにみえる)なら、3レベルともキャッシュされます。
(3)(4)のように、URLが「キャッシュ対象拡張子」で終わっていない場合は、3レベルともキャッシュされません。

レベル設定で挙動が変わるのは、
(5)のような「キャッシュ対象拡張子で、クエリ文字列がある場合」です。

(※1) Simplifiedではクエリ文字列は削られるけど……?

キャッシュレベルがSimplifiedで、上記表の(5)のパターン、つまり「キャッシュ対象拡張子・クエリ文字列あり」の場合、次のような挙動になります。
  1. エッジサーバーからオリジンサーバーへは、クエリ文字列を取り除いてリクエストが送られる
  2. ただしキャッシュ内容はクエリ文字列付きのURLごとにそれぞれ保持される

ユーザー file.js?with=query
→①→

←④←
file.js?with=query
CloudFlare
エッジ
サーバー
file.js
→②→

←③←
file.js
オリジン
サーバー

挙動Aは文字どおりですが、Bがちょっと理解しにくいので、具体例で見てみます。
次のような、日時とURIをJavaScriptで出力するCGIスクリプトを用意しました。

#/usr/bin/ruby
puts "Content-type:application/javascript"
puts
puts "document.writeln('#{Time.now.to_s}');"
puts "document.writeln('#{ENV['REQUEST_URI']}');"
このCGIスクリプトに、js.cgi/pathinfo.js?with=query という形でアクセスしてみます。
$ curl -i 'http://cloudflare.example.jp/js.cgi/pathinfo.js?with=query'
HTTP/1.1 200 OK
CF-Cache-Status: MISS

document.writeln('Mon Mar 04 00:30:00 +0900 2013');
document.writeln('/js.cgi/pathinfo.js');

$ curl -i 'http://cloudflare.example.jp/js.cgi/pathinfo.js?with=query'
HTTP/1.1 200 OK
CF-Cache-Status: HIT

document.writeln('Mon Mar 04 00:30:00 +0900 2013');
document.writeln('/js.cgi/pathinfo.js');
1回目のアクセスでキャッシュが作られ、2回目のアクセスではそのキャッシュが返ってきています。
ENV['REQUEST_URI'] が「pathinfo.js」で終わっていて、「?with=query」が付いていません。クエリ文字列はエッジサーバーが切り落としたようです。

ここで、クエリ文字列を変えてアクセスしてみます。
$ curl -i 'http://cloudflare.example.jp/js.cgi/pathinfo.js?with=query2'
HTTP/1.1 200 OK
CF-Cache-Status: MISS

document.writeln('Mon Mar 04 00:32:22 +0900 2013');
document.writeln('/js.cgi/pathinfo.js');

$ curl -i 'http://cloudflare.example.jp/js.cgi/pathinfo.js?with=query2'
HTTP/1.1 200 OK
CF-Cache-Status: HIT

document.writeln('Mon Mar 04 00:32:22 +0900 2013');
document.writeln('/js.cgi/pathinfo.js');
さっきとは別のキャッシュがエッジサーバーに作られました。(Time.nowの出力する日時もさっきと違います)
しかし ENV['REQUEST_URI'] はこちらもさっきと同じ「/js.cgi/pathinfo.js」です。

というわけで、オリジンサーバーに対してはクエリ文字列を削った状態でアクセスしにくるけど、キャッシュはそれぞれ作成されるというよく分からない挙動です。
どうせクエリ文字列を切り落とすなら、キャッシュも共有してくれたほうが嬉しかったかも。

ちなみに、表の(2)のケースではクエリ文字列は削られずにオリジンサーバーに渡ります。
$ curl -i 'http://cloudflare.example.jp/js.cgi?q=.js'
HTTP/1.1 200 OK
CF-Cache-Status: MISS

document.writeln('Mon Mar 04 00:35:00 +0900 2013');
document.writeln('/js.cgi?q=.js');

(※2) Aggressiveでクエリ文字列がある場合、すぐにはキャッシュは作られない?

続いてキャッシュレベルがAggressiveで、キャッシュ対象拡張子・クエリ文字列ありの場合。
次のような挙動になります。

  1. 同一URL(同一クエリ文字列)に複数回アクセスがあっても、すぐにはキャッシュを作らない
  2. 何回かアクセスがあったらキャッシュを作り、以降のアクセスはキャッシュを返す
$ curl -i 'http://cloudflare.example.jp/js.cgi/pathinfo.js?with=query'
HTTP/1.1 200 OK
CF-Cache-Status: MISS

document.writeln('Mon Mar 04 00:40:00 +0900 2013');
document.writeln('/js.cgi/pathinfo.js?with=query');

$ curl -i 'http://cloudflare.example.jp/js.cgi/pathinfo.js?with=query'
HTTP/1.1 200 OK
CF-Cache-Status: MISS

document.writeln('Mon Mar 04 00:40:11 +0900 2013');
document.writeln('/js.cgi/pathinfo.js?with=query');

$ curl -i 'http://cloudflare.example.jp/js.cgi/pathinfo.js?with=query'
HTTP/1.1 200 OK
CF-Cache-Status: MISS

document.writeln('Mon Mar 04 00:40:22 +0900 2013');
document.writeln('/js.cgi/pathinfo.js?with=query');

$ curl -i 'http://cloudflare.example.jp/js.cgi/pathinfo.js?with=query'
HTTP/1.1 200 OK
CF-Cache-Status: HIT

document.writeln('Mon Mar 04 00:40:22 +0900 2013');
document.writeln('/js.cgi/pathinfo.js?with=query');
最初の3回はオリジンサーバーにアクセスが行っていますが、4回めでキャッシュが返ってきました。

キャッシュを作る条件が「同一クエリで(一定期間中に?)3回アクセスがあったら」なのかどうかは不明ですが、いきなりキャッシュが作られて使われるわけではないのは要注意。

たぶん検索フォームなどで「よく検索されるワードの検索結果はキャッシュして、あまり検索されないワードの検索結果は(ロングテールになってエッジサーバーのキャッシュヒット率が悪そうなので)キャッシュしない」という使われ方を想定しているんじゃないかと。

次回:キャッシュレベル設定では選べない特殊メニュー「Cache everything」

この記事では3種類のキャッシュレベルの挙動の違いを見ましたが、実は「パフォーマンス設定」の画面からは選べない第4の選択肢が存在するのです。それが「Cache everything」。

次の記事では、この「Cache everything」の挙動を確認します。

2 件のコメント:

  1. > (1)や(2)のように、URLが「キャッシュ対象拡張子」で終わっていない場合は、3レベルともキャッシュされません。
    > (3)(4)のように、URLがキャッシュ対象拡張子で終わっている(ようにみえる)なら、3レベルともキャッシュされます。

    (1)(2)と(3)(4)の説明が逆では?

    返信削除
    返信
    1. ご指摘ありがとうございます。おっしゃるとおりです。修正しました。

      削除