« C-0.05 | メイン | cygwin + mod_perl »

2006年02月08日

キャッシュの上手な使い方

 キャッシュといっても、ウェブブラウザやウェブプロキシのキャッシュのことです。

・Internet Explorer のキャッシュの動作

 Internet Explorer は、同一ウィンドウ内で複数回同じウェブページを読み込む場合、2回目以降はキャッシュのデータを使用します (デフォルト設定の場合、 Last-Modified または Expires ヘッダがついている場合のみ)。
つまり、同じウィンドウの中で、 ページA を読み、次にページB を読み、そしてページA を再び読み込むようなケースでは、2回目にページ A を表示する際にはキャッシュのデータが使用され、ウェブサーバへの再問い合わせは行われません。
 また、 Last-Modified ヘッダと Expires ヘッダの双方が返されている場合、Expires の期限が切れるまで、再問い合わせは行われません注1

・Mozilla Firefox のキャッシュの動作

 Mozilla Firefox は、一度取得したページについては、Last-Modified ヘッダからページの有効期間を推測して、その期間が過ぎるまではキャッシュを使い続けます。有効期間の予測式は、(キャッシュ日時-最終更新日時)÷10 注2 です。つまり、最終更新されてから 100 日経過したコンテンツをキャッシュした場合、そのキャッシュデータは 10 日間使用されます。
 また、Expires ヘッダが返されている場合、その期限が切れるまで、再問い合わせは行われません。

・Squid のキャッシュの動作

 Squid の動作は、Firefox とほぼ同じです。ただ、予測式の分母が 10 ではなく 5 になります。また、
  ・キャッシュの有効期間は最大3日
  ・Squid 管理者の設定により、予測式を変更可能
  ・URL に ? が含まれる場合はキャッシュしない
といった差があります。


以上を踏まえて、ウェブサイトの最適化手法

 レスポンスの良いウェブサイトを作りたい、ウェブサイトの負荷を下げたい、といったケースでは、このようなキャッシュの動作を踏まえて、ロゴマークの画像ファイルや JavaScript ファイル等のスタティックコンテンツを配置すべきです。一方で、コンテンツを更新した暁にはブラウザが速やかにそのコンテンツを取得してくれるよう、調整しておく必要もあります。
 このような条件を満たすファイルの配置ルールは、以下のようになるでしょう。

・最適化レベル1 - Last-Modified を返す

 Last-Modified ヘッダを返すことにより、ブラウザのキャッシュが有効化されます。
 上に述べたようなルールで、再読み込みの抑制が行われるほか、たとえ再読み込みが行われる場合でも、条件付 GET リクエストが発行されるようになるので、不要な再転送が発生しないようになります。これにより、バンド幅の節約/ロード時間の短縮が図れます。

・最適化レベル1.1 - 静的コンテンツを変更する場合は、ファイル名を変える

 Last-Modified を返していると、必要な時にブラウザが再読み込みしてくれないことがあります。
 たとえば、CGI から呼び出される .js ファイルの JavaScript の関数を変更した際、旧バージョンの .js ファイルがキャッシュされていると、新しい CGI ページから古い .js ファイルの関数が呼び出される、といったことが起こってしまいます。最悪なケースは、複数の異なる最終更新時刻をもつ .js ファイルをインクルードしている場合で、こうなると、もう原因を確認することすら難しくなります。
 Last-Modified を返す静的コンテンツについては、更新時にファイル名を変えるのが必須と言えるでしょう。

・最適化レベル2 - 静的コンテンツに ? をつけない

 キャッシュが抑制されるケースがあるので、キャッシュ可能なコンテンツに ? を含めるのは控えるべきです。

・最適化レベル3 - 静的コンテンツの数を減らす

 上で述べたように、たとえば Internet Explorer では、ウィンドウを開くたびに条件付 GET リクエストが発行されます。そこで、条件付 GET リクエストを抑制することで、クライアント側ではページのロード完了までの時間が短縮され注3、また、サーバ側の負荷を下げることが次の目標になります。
 具体的には、複数の script ファイルをひとつにまとめたり、複数ある空白の画像 URL を統一したりすることが挙げられるでしょう注4

・最適化レベル4 - Expires ヘッダを返す

 究極の最適化は、 Expires ヘッダを返すことです。
 レベル 1.1 で述べたように、静的コンテンツについては、更新時にファイル名を変える必要があります。それならばいっそ、 Expires ヘッダを付与することで、はるか未来までキャッシュしてもらえばいいわけです。
 たとえば Apache の場合なら、設定ファイルに

<Directory "/home/www/htdocs/static">
ExpiresActive On
ExpiresDefault "access plus 10 years"注5
</Directory>

などと設定することで、ブラウザの再問い合わせを半永久的に抑制することができます。

 ここまですれば、ウェブブラウザが問い合わせるのは動的コンテンツのみになるので、AIREDGE のように遅延が長い環境でも、快適なウェブサイトが構築できると思います。

注1: Last-Modified ヘッダがなく Expires ヘッダのみがある場合、ウィンドウを開くたびに再問い合わせが行われるようです
注2: キャッシュ日時の判断にはサーバの Date ヘッダが使用されるので、時計のズレは問題にならない
注3: リクエストを投げて、レスポンスを受け取って、の繰り返しになるので、転送量よりも遅延が問題になります
注4: script.aculo.us の手法は、レベル2,3 に反してるので、特に2回目以降のアクセスの場合、非効率だと思います。また、バージョンアップの際にディレクトリを変えるようにしないと、レベル 1.1 の問題が発生することになります
注5: (10:06 追記) 2038年問題があるので、あまり大きな値にしないほうが無難でしょう。"100 years" とすると動作しないケースが出てくるでしょうし、仮に "30 years" としてしまうと、2008 年に動かなくなってしまいます。

投稿者 kazuho : 2006年02月08日 01:00 このエントリーを含むはてなブックマーク このエントリーを含むはてなブックマーク

トラックバック

このエントリーのトラックバックURL:
http://labs.cybozu.co.jp/cgi-bin/mt-admin/mt-tbp.cgi/392

このリストは、次のエントリーを参照しています: キャッシュの上手な使い方:

» コメントが反映されないよ問題についての考察 from ClearGreen
Movable Typeのダイナミック・パブリッシングを使っているので、 動的生... [続きを読む]

トラックバック時刻: 2006年03月16日 02:13

» フロントエンドのパフォーマンスチューニング - Expiresヘッダ追加 from Shoulder.jp
Postgresqlのパフォーマンスチューニングについて書いてきたけど、Webサイトのパフォーマンスには、そういったバックエンドだけでなく、フロントエンド... [続きを読む]

トラックバック時刻: 2008年02月01日 07:02

» Link/Security/articles from [ abs+ ] (PukiWiki/TrackBack 0.3)
Link/Security/articles ▲ ▼その他セキュリティ関連(未分類) @police:分析レポート「SSHを利用した不... [続きを読む]

トラックバック時刻: 2009年05月01日 21:36

コメント

Squidは設定でいくらでも変更できるし、またそれが普通なのであまり参考にならないかも。

つうか、設定項目大杉。

Dan the Squid Tamer

投稿者 : 2006年02月19日 00:17

コメントありがとうございます。

squid の件、異論ありません。まあ、マニア^H^H^H管理者向けのソフトですし (苦笑)

投稿者 kazuho : 2006年02月25日 01:09