落とし穴に注意−本連載では、現場でのエンジニアの経験から得られた、アプリケーション・サーバをベースとしたWebシステム開発における注意点やヒントについて解説する。巷のドキュメントではなかなか得られない貴重なノウハウが散りばめられている。読者の問題解決や今後システムを開発する際の参考として大いに活用していただきたい。});今回のワンポイントWebシステムのパフォーマンスを考慮するうえで、実はコンテンツのキャッシュに関する知識は欠かせない。今回はブラウザ側のキャッシュ、サーバ側のキャッシュをいかに制御し、Webシステムのパフォーマンスを向上させるかについて解説する。キャッシュされる場所は3カ所コンテンツがキャッシュされる場所は、図1のように大きく分けて以下の3つの場所がある。クライアントマシン上のブラウザクライアントマシンとWebサーバの間に位置するProxyサーバWebサーバの背後にあるアプリケーションサーバキャッシュをうまく制御することによって、システムの正しい動作を保証するだけではなく、応答時間の短縮、回線の有効活用、サーバリソースの節約といった重要な性能対策になる。本稿では、HTTPのキャッシュ機構の説明とともに、キャッシュを有効活用するための指針、ブラウザのキャッシュ機構が正常に動作しないというトラブル事例について述べる。本稿ではアプリケーションサーバのキャッシュ機能については割愛する。キャッシュされる場所は「クライアント」「Proxyサーバ」「APサーバ」の3カ所にあるキャッシュ制御の方法サーバサイドからキャッシュを制御するには、以下の2つの方法がある。HTTPヘッダによる制御METAタグによる制御まずは、これらがどのようなものか、軽くおさらいしておく。■HTTPヘッダによる制御HTTPプロトコルでは、HTTPヘッダにさまざまな情報を格納することができる。そのうちいくつかの情報は、キャッシュ制御のためのヘッダである。リクエスト(クライアント→サーバ)用のものと、レスポンス(サーバ→クライアント)用、リクエスト/レスポンス共通のものが存在する。■リクエスト用If-Modified-Since日時を指定する。指定した日時より新しいコンテンツの場合のみデータを返却するようにサーバに指示する。ローカルキャッシュの最新確認に使用されるIf-None-Match指定したエンティティタグに一致しない場合のみコンテンツを返却するようにサーバに指示する。最新情報の取得や競合の排除のために指定される■レスポンス用Expiresコンテンツの有効期限を示すLast-Modifiedコンテンツの最終更新時刻を示す。If-Modified-Sinceと対で使用されるETagコンテンツの全体や一部を特定する固有値を示す。If-None-Matchと対で使用される■リクエスト/レスポンス共通Cache-Controlキャッシュのコントロールに関する指示や情報を示すPragma関連するクライアント/Proxy/サーバそれぞれに認識させるための特殊な追加情報を記述する。「no-cache」を指定することで無条件に最新リソースを転送させることができる■METAタグMETAタグはHTMLで規定されていない情報をHTMLページに持たせるためのタグだ。contentというフィールドを追加したのと同じ働きとなる。そのため静的なHTMLコンテンツの内部からクライアントのキャッシュを制御することが可能となる。METAタグは基本的にはブラウザのキャッシュを操作するためのものだ。通常はProxyサーバはMETAタグを処理しないからである。ブラウザの種類によってはMETAタグをサポートしないものがあるので、確実にキャッシュをコントロールしたい場合には、HTTPヘッダとMETAタグの両方を使用するのがよいだろう。キャッシュの流れブラウザやProxyサーバにコンテンツがキャッシュされる場合の動作は次のようになる。コンテンツがブラウザ内にキャッシュされた場合、ブラウザがそのコンテンツのキャッシュを使用する場合にはサーバに対してリクエストを発行しない。ブラウザ内にキャッシュがない場合や、キャッシュを使用するかどうか判断できない場合には、サーバにリクエストを発行する。コンテンツがProxyサーバにキャッシュされている場合、Proxyサーバではコンテンツと一緒にHTTPヘッダ情報を保存している。キャッシュが有効な場合にはブラウザからのリクエストに対してProxyサーバがレスポンスを返す。Proxyサーバでは、異なるクライアント(ブラウザ)が以前にリクエストしたコンテンツをキャッシュし、そのキャッシュを使用することができる。キャッシュが無効な場合や、キャッシュを使用しないことを指示されている場合には、ProxyサーバはWebサーバに対してコンテンツを取得するためにリクエストを発行する。リクエストがWebサーバまで到達すると、If-Modified-SinceヘッダやIf-None-Matchヘッダが付いていた場合、WebサーバはコンテンツのタイムスタンプとIf-Modified-Sinceヘッダの時間、コンテンツの全体や一部を特定する固有値とIf-None-Matchヘッダの値を比較し、もしコンテンツが更新されていればコンテンツを送信する。レスポンスとして返す。Modified」の場合にはレスポンスボディに実際のファイルを含まないヘッダだけのレスポンスなため、非常に軽量のデータである。キャッシュの流れ何でもキャッシュすればよいわけではないWebシステムをWebサーバ、アプリケーションサーバを連携させて構築する場合、画像ファイルやCSSファイル、めったに更新されないHTMLファイルなどの静的なコンテンツは、通常Webサーバに配置しアプリケーションサーバの負荷を減らすようにする。そのためWebサーバでは適切なヘッダを送信するように正しく設定する必要がある。アプリケーションサーバで生成されるコンテンツは、通常、ユーザーのセッション情報やDBアクセスなどを基に動的に生成されるものである。そのためブラウザ、Proxyサーバにキャッシュされてしまうと、検索結果がいつまでも更新されなかったり、ほかのユーザーが検索した結果が参照できてしまったりするなどの不具合が発生する可能性がある。そのためキャッシュされないようにするためのキャッシュコントロールが必要である。J2EEアプリケーションサーバでは動的なHTMLページを生成するのにJSPが使用される。そこでJSPで生成したページをキャッシュさせないようにするための方法を紹介する。include="Nocache.inc"%>のようにインクルードするとよい。getHTTPDate());response.setHeader("Pragma","no-cache");response.setHeader("Cache-Control","no-cache");%>また、レスポンスヘッダは以下のようになる。close負荷分散装置でキャッシュが効かないのは?負荷分散装置を利用したWebサーバ、アプリケーションサーバのクラスタ化は、パフォーマンスやスケーラビリティの向上のために採用されることが多い。ここでは、負荷分散装置を利用したWebサーバのクラスタ化において、Webサーバ(Apache)の設定によりキャッシュが有効とならなかった事例を紹介しよう。システムは図3のように、Webサーバ、アプリケーションサーバを分割し、Webサーバは静的コンテンツのみ、アプリケーションサーバは動的コンテンツを処理するようになっていた。Webサーバは多重化され、セッション情報などを持たないため負荷分散装置によってラウンドロビンに振り分けられていた。問題となったシステム構成Webサーバに配置されたコンテンツは主に画像ファイルで、応答時間劣化の懸念となっていた。画像ファイルは多くの遷移先ページで同一の画像を使用しており、まためったに更新されないことが分かっていた。事実Webサーバが1台の場合の試験環境ではブラウザのキャッシュが有効となり、応答時間が改善されることが確認できていた。実際のシステムでの状況は、画像へのリクエストに対して、期待されたレスポンスコード304を全く返さず、ほぼ毎回レスポンスコード200として画像ファイルを送信してしまっていた。そのため応答時間も悪化、Webサーバの負荷も上がってしまった。■原因はHTTPヘッダのETag原因は、先ほど説明したHTTPヘッダのETagであった。このETagはコンテンツに対してユニークなIDを割り振り、変更されているかどうかを確認するためのものである。ブラウザからはIf-None-Matchタグにこの値が付けられ、サーバ側ではこの値とETagの値が異なればレスポンスコード200でコンテンツを送信する。ETagの値は、同じ内容、同じ更新日付のファイルであってもWebサーバごとに異なる値が返されていた。今回使用していたシステムではApacheを採用していたのだが、Apacheはファイルのi-nodeによりユニークなIDを付けていた。リクエストを負荷分散装置がラウンドロビンで振り分けていたため、同じWebサーバにアクセスが行かない限り異なるコンテンツと判断され、結果が送信されていたのだ。1.3.23以降では、サーバ側でETagを付けないことにより、ETagによる比較を行わなくすることが可能だ。None」と記述すればよい。以下にいくつかの設定例を示す。None今回の記事ではHTTPのキャッシュ機構、J2EEでのキャッシュの制御方法、キャッシュに関するトラブル事例を紹介した。キャッシュによる効果は、クライアントからすれば応答時間の短縮、サーバからすれば、サーバリソースの節約に非常に大きく発揮される。そのためキャッシュの仕組みを知り、正しく制御することはとても重要である。トラブル事例のときのように、試験環境と本番環境が異なる場合には特に注意が必要である。うっかり設定を見落とすことによって、避けられるはずの顧客のイライラやサーバの過負荷によるシステム管理者の悲鳴などに遭遇しないように注意するべきだ。ゆき)現在、株式会社NTTデータビジネス開発事業本部に所属。技術支援グループとして、J2EEをベースにしたWebシステム開発プロジェクトを対象に、技術サポートを行っている。性能・信頼性といった方式技術を中心に活動中。メールマガジンをご購読ください。申し込みページへITmediaはアイティメディア株式会社の登録商標です。