CloudFrontで「Forward Cookies」を「All」にしている時に注意すべき点
菅野です。
先日、CloudFront経由でウェブページにアクセスした時に常に「X-Cache: Miss from cloudfront」となるので調査したところ、CloudFrontの「Behavior」の「Forward Cookies」が「All」になっている事が原因でした。
今回はなぜ「All」だとキャッシュが使われなかったのか、CloudFrontにおけるcookieの注意点について書こうと思います。
webページを準備
EC2インスタンスを立ち上げ、apacheとphpをインストールします。
/var/www/html/index.phpを作成し、内容は以下にします。
GoogleAnalyticsもcookieを使うので検証の為に埋めました。
<?php setcookie( "cookie01", "value01" ); // setcookie( "cookie02", date('Y/m/d H:i:s') ); setcookie( "cookie02", "" ); ?> <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8" /> <title>テストwebページ</title> </head> <body> <span>これはテストページです</span><br> <script> (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) })(window,document,'script','https://www.google-analytics.com/analytics.js','ga'); ga('create', 'UA-********-*', 'auto'); ga('send', 'pageview'); </script> <br> ------------------------------------------------------<br> cookie<br> ------------------------------------------------------<br> <?php $tmp_str = json_encode( $_COOKIE ); $tmp_str = preg_replace( '/([,{])/', '${1}'."\n".'<br>', $tmp_str ); $tmp_str = preg_replace( '/}/', "\n".'<br>}', $tmp_str ); echo $tmp_str; echo '<br>'; ?> ------------------------------------------------------<br> </body> </html>
このページにアクセスすると以下のような結果が得られ、webサーバーにどのようなcookieが渡されているか確認できます。
CloudFrontを準備
CloudFrontのページを表示し、「Create Distribution」をクリックして新しく「Distribution」を作成します。
作成は簡単で、「Origin Domain Name」に先ほど作成したEC2の「パブリック DNS」を入力するだけでOKです。
CloudFrontは作成が完了するまで時間が掛かります。設定を変更した時も同様なので実際に試す時はその点を覚悟してください。
「Forward Cookies」が「None」の場合
「Forward Cookies」はデフォルトで「None」になっていて、この状態はoriginに指定したwebサーバーに対して一切cookieを渡しません。
では、CloudFrontを経由して先ほど作成したwebサイトにアクセスして確認してみましょう。
URLはCloudFrontの「Domain Name」になります。
結果は以下のようになり、webサーバーに対してcookieが一切渡されていない事がわかります。
次に、数回更新した後でchromeの基本機能を使ってCloudFrontのキャッシュが使われているか確認します。
確認用URL:chrome://net-internals/#events
「type:URL_REQUEST」でフィルタすると使いやすいのでおすすめです。
結果は以下のようになります。
HTTPヘッダに「X-Cache: Hit from cloudfront」と表示されていますので、キャッシュされてそれを使ったことがわかります。
「webサイトでcookieを使いたいのに渡ってこないのでは困る」といった場合は「Forward Cookies」を「None」で運用できません。
では「All」での運用はどのような状況になるか検証してみましょう。
「Forward Cookies」が「All」の場合
さっそくこの状況で何回かアクセスしてみましょう。結果は以下のようになります。
表示内容はwebサーバーに直接アクセスした時となんら変わりませんね。
ではHTTPヘッダはどうなっているのか確認します。
キャッシュにHitしています。この状態で問題無さそうに見えますがCloudFrontはcookieの値も含めてキャッシュを使うか判断していますので値が異なる場合はキャッシュが使われません。
その部分を理解する為にwebページのソースを少し変更し、3行目のコメントアウトを解除し、4行目をコメントアウトします。
<?php setcookie( "cookie01", "value01" ); setcookie( "cookie02", date('Y/m/d H:i:s') ); // setcookie( "cookie02", "" ); ?> <!DOCTYPE html> <html lang="ja"> 略
この状態で何度かアクセスしてみましょう。以下のようにcookieに日時が登録されていて、アクセスする度に変更されている事もわかります。
では、このようにアクセスする度にcookieの値が変わるページの場合、CloudFrontのキャッシュは使われのでしょうか?
先ほどと同じようにHTTPヘッダを確認します。
X-Cache: Miss from cloudfront
X-Cache: Miss from cloudfront
X-Cache: Miss from cloudfront
何度アクセスしてもキャッシュが使われません。
「Forward Cookies」が「All」で「cookieの値が変動した時」はCloudFrontは別のキャッシュを作成するので前回のキャッシュは使われないのです
ではどんな問題が?
さきほど、「Forward Cookies」が「All」の場合はcookieの値によって別キャッシュとなる事がわかりました。
ではどんな問題があるの?と言われると運用しているwebサイトによっては問題ないかもしれませんが、最早入れててあたりまえという感じのGogleAnalyticsタグはどうでしょう?
まずは日時のcookieを無効化し、今度は別のブラウザでアクセスしてみます。
「_ga」の値が変わっています。
chrome:GA1.3.1433833158.1463106328
safari:GA1.3.1375323490.1463121195
キャッシュが本当に使われていないのか、safariで数回アクセスした後すぐにchromeでアクセスしてみます。
Missとなりました。もちろん、もう1回アクセスするとHitになります。
このように、「Forward Cookies」が「All」で「GoogleAnalytics」のタグを埋めている場合、各ユーザーさらに各ブラウザ毎にキャッシュが作成されるのでHit率が悪くなります。
ではどうすればいいの?
CloudFrontの「Forward Cookies」には「Whitelist」というものも用意されています。
ここに「GoogleAnalyticsのCookie以外」を登録すればいいのです。
ページにアクセスしてwebサーバーに渡っているcookieを確認します。
GoogleAnalyticsのcookieは渡されていません
この状態でSafariから数回、すぐにchromeからアクセスして確認します。
このようにCloudFrontのキャッシュが使われました。
さいごに
いかがでしたでしょうか。
今回このエントリーを書くきっかけは、「CloudFrontでキャッシュにHitしない」という問題の調査でした。
Google先生に幾度となく質問をしたのですが、CloudFrontのキャッシュのTTLについてのエントリーは多数出てくるけど「CloudFrontがキャッシュしない条件」についての情報が見つからないという状況で、
単純なページを作成して検証するとキャッシュされ、問題のページのソースをコピーするとキャッシュされないことがわかり、ためしにGoogleAnalyticsのタグを消してみたらキャッシュされました。
世の中でこれだけ使われているGogleAnalyticsとCloudFrontの組み合わせで問題が起きていないのか?とも思いましたが、「None」で使っている場合は問題ないですし、ブラウザを変えるとキャッシュがHitしないが2回目からはHitするので、Hit率が悪くなっている事に気づいていない可能性もあります。
CloudFrontを「Forward Cookies」に「All」や「Whitelist」を設定して利用する時は、cookieに何が渡されているのかを確認し、場合によっては「Whitelist」を使って必要なcookieだけを渡す設定が必要だという事を覚えておいてください。
このエントリーを見た方がCloudFrontの「Forward Cookies」について確認・検討するきっかけになれば幸いです。
参考ページ
これらのページを参考にさせていただきました。
ありがとうございました。
[Server & Network] Chrome Developer Tools で HTTP Header を確認する方法
Cloudfrontでヘッダー情報が更新されないとかその手のもの
ふつうのWebサイトの負荷軽減におけるCloudFront