Apache Traffic Serverを利用する場合、注意したいのがキャッシュの設定だ。特に動的なコンテンツを配信するサイトや、ログインなどが必要でユーザー毎に異なるコンテンツを送信する場合、この設定を間違えると情報漏洩などに繋がる可能性もある。今回はTraffic Serverのキャッシュ設定について説明する。

Apache Traffic Serverにおけるキャッシュの考え方

本記事前編で紹介したとおり、Traffic Serverはクライアントとコンテンツを配信するWebサーバー(オリジンサーバー)を中継し、さらにその際にコンテンツをキャッシュする仕組みを持っている。これによってキャッシュ済みURLへのリクエストについてはオリジンサーバーにリクエストを送ること無しにレスポンスを返せるようになり、オリジンサーバーの負荷軽減やレスポンス速度の向上が期待できるのだが、こうしたアーキテクチャを取る場合に注意したいのが、オリジンサーバーで配信されるコンテンツの中身が変更された場合にキャッシュが十分な速度で更新されるかどうかだ。たとえば短い間隔で更新されるようなコンテンツの場合、キャッシュの有効期間を長く設定してしまうと更新がクライアントに反映されるのが遅くなってしまう。いっぽうであまり更新されないコンテンツに対し、キャッシュの有効時間を短く設定してしまうとキャッシュ効果が薄れてしまう。

Traffic Serverではさまざまなケースに対応するため、多くのキャッシュ関連パラメータが用意されており、さらにURLやオリジンサーバー毎に異なるキャッシュ設定を適用できるようになっている。

Apache Traffic Serverのキャッシュアーキテクチャ

キャッシュ設定について詳しく解説する前に、Traffic Serverの基本的なキャッシュアーキテクチャについて紹介しておこう。Traffic Serverではオリジンサーバーに対しなるべくコンテンツのリクエストを行わないようにしながらキャッシュの有効性を確認できるような仕組みが導入されている。

Traffic Serverは、キャッシュが許可されているURLに対するリクエストを受けると、まずそのリクエストのキャッシュが許可されているかどうかをチェックする。Traffic Serverのデフォルト設定では基本的にはすべてのリクエストがキャッシュされるように設定されているが、たとえばクライアントがリクエスト内に「Cache-Control:」ヘッダーでキャッシュを利用しないよう明示するケースがある。また、サーバー側の設定によって特定の条件に合致するリクエストに対してはキャッシュを行わないように設定することが可能だ。もしキャッシュが許可されていなければ、オリジンサーバーにリクエストを送信してその結果をそのままクライアントに転送する。

もしキャッシュが許可されていれば、続いてキャッシュデータベース内にそのコンテンツが保存されているかどうかを確認する。もしキャッシュデータベース内にそのコンテンツが存在しなければ、オリジンサーバーにリクエストを行ってコンテンツを取得し、それをクライアントに送信するとともにキャッシュデータベース内に保存する(図1)。

図1 Apache Traffic Serverのキャッシュ動作
図1 Apache Traffic Serverのキャッシュ動作

いっぽう、キャッシュデータベース内にそのコンテンツが存在していた場合、次にそのキャッシュの「新鮮さ」(stale)を確認する。もし「新鮮」であれば、キャッシュから取り出したデータをクライアントに送信する(図2)。

図2 Apache Traffic Serverでは「キャッシュの新鮮さ」をチェックする
図2 Apache Traffic Serverでは「キャッシュの新鮮さ」をチェックする

もしコンテンツが「新鮮」でなければ、Traffic Serverはオリジンサーバーに「If-Modified-Since」ヘッダ付きのリクエストを送信してコンテンツが更新されていないかを確認する(図3)。

図3 キャッシュが「新鮮」でない場合、オリジンサーバーにコンテンツが更新されていないかの問い合わせを行う
図3 キャッシュが「新鮮」でない場合、オリジンサーバーにコンテンツが更新されていないかの問い合わせを行う

Webサーバーはこのヘッダ付きのリクエストを受け取った場合、コンテンツが指定した日付以降に更新されていなければコンテンツを送信する代わりに「304(not modified)」というHTTPステータスコード返送する。この場合、キャッシュに格納されているコンテンツはまだ有効であるため、Traffic Serverはキャッシュから取り出したデータをクライアントに送信するとともに、キャッシュの新鮮さの期限を更新する。

もしオリジンサーバーが304以外のレスポンスを返した場合、Traffic Serverはオリジンサーバーからコンテンツを取得し、キャッシュに保存すると同時にクライアントに送信する(図4)。なお、オリジンサーバーがTraffic Serverからの問い合わせに応答しない場合、「111 Revalidation Failed」レスポンスでキャッシュされたコンテンツを送信する。

図4 コンテンツが更新されていた場合、それを再度キャッシュする
図4 コンテンツが更新されていた場合、それを再度キャッシュする

「新鮮さ」の判別アルゴリズム

さて、Traffic Serverではこのような手順でキャッシュの制御を行っているのだが、それではTraffic Serverではどのようにして「新鮮さ」を判定するのだろうか。

Traffic Serverがまず指標として使用するのが、Webサーバーがレスポンスを返す際に付与する「Expires:」ヘッダや「Cache-Control:」ヘッダだ。Expires:ヘッダはそのコンテンツの有効期限を時刻で指定するもので、Traffic Serverは現在時刻がこの時刻よりも後の場合、キャッシュが新鮮ではないと判断する。また、Cache-Control:ヘッダはキャッシュの挙動を制御するためのヘッダで、複数のパラメータが指定できる。もしCache-Control:ヘッダ内にキャッシュ期限を設定する「max-age=」パラメータが指定されていた場合、そのキャッシュが作成/更新されてから指定した時間(秒)の間はキャッシュが新鮮であると判断される。たとえば以下のようなヘッダが付与されていた場合、キャッシュが新鮮である期間は60秒となる。

Cache-Control: max-age=60

Expires:ヘッダやCache-Control:ヘッダのmax-ageパラメータが指定されていない場合、そのコンテンツの作成日を示す「Date:」ヘッダや、最終更新日を示す「Last-Modified:」ヘッダの情報を使用し、次の式で新鮮である期間が算出される。

(現在時刻 - 作成日/最終更新日)× 係数

ここで、係数はデフォルトでは0.1となっている(設定で変更可能)。たとえば作成日が2017年1月1日0時、現在時刻が2017年1月11日0時だった場合、新鮮である期間は1日間となる。

(2017年1月11日 - 2017年1月1日) × 0.1
=10日間×0.1
=1日間

一見すると意味が分かりにくいが、作成日/最終更新日から時間が経っているコンテンツは更新頻度が少ないものと判断し、より長い期間新鮮であると判断するという考え方だ。

また、Date:ヘッダおよびLast-Modified:ヘッダの両方がない場合、あらかじめ設定されている新鮮である期間の最大値/最小値を使用して判断を行うことになる。

なお、クライアントから送られたリクエストでキャッシュ制御を指定するCache-Control:ヘッダが指定されていた場合、キャッシュの新鮮さを判断する際にそこで指定されたパラメータが使用される。たとえば「min-fresh」パラメータが指定されていた場合、コンテンツの最終更新日(最終更新日の情報がない場合は作成日)からここで指定された数値(秒)以上の時間が経過していれば、強制的にTraffic Serverはそのコンテンツが新鮮でないと判断する。いっぽう、「max-stale」パラメータが指定されていた場合、もしTraffic Serverがそのコンテンツについて新鮮でないと判断しても、そのコンテンツが更新されているかどうかをオリジンサーバーに問い合わせること無しにキャッシュからの配信を行えるようになる。

Apache Traffic Serverにおけるキャッシュ条件のカスタマイズ

Traffic Serverでは、以上のように「新鮮さ」というパラメータを用いてキャッシュを管理している。しかし、サイトによってはキャッシュされると問題が発生するページなども存在する。さらに、静的なページはなるべく長時間キャッシュを保持してもらい、動的に生成されるページはキャッシュの保持時間を短くしたい、といった要求もあるだろう。続いては、こういったキャッシュ条件をカスタマイズする方法について紹介する。

キャッシュが行われないコンテンツ

Traffic Serverのデフォルト設定では、リクエストヘッダでキャッシュを行わないよう指示されているリクエストに対するレスポンスや、レスポンスヘッダでキャッシュに関する特定の設定が行われているレスポンスについてはキャッシュを行わない。

まずリクエストヘッダについてだが、下記のものが付与されている場合Traffic Serverはキャッシュを利用せず、毎回オリジンサーバーにリクエストを転送してその結果をクライアントに送信する。また、そのコンテンツのキャッシュも行わない。

  • Cache-Control:ヘッダに「no-cache」もしくは「no-store」が指定されている
  • 「Authorization:」ヘッダが付与されている

ここで挙げられている「Authorization:」ヘッダは、BASIC認証などの認証情報を送信するために使われるものだ。また、オリジンサーバーが送信するレスポンスヘッダ内に次のものが付与されている場合も、そのコンテンツのキャッシュは行わない。

  • Cache-Control:ヘッダに「no-store」もしくは「private」、「no-cache」が指定されている
  • WWW-Authenticate:ヘッダが付与されている
  • Set-Cookie:ヘッダが付与されている
  • Expires:ヘッダの値が0、もしくは過去の日付

WWW-Authenticate:ヘッダは、BASIC認証などの認証を要求するヘッダだ。また、Set-Cookie:ヘッダはCookieを送信するためのヘッダだ。これらが付与されているリクエストについても、クライアントによってコンテンツが変わる可能性があるためにキャッシュされないようになっている。

ただし、これらの挙動についてはTraffic Serverの設定によって変更することができる。たとえばリクエストヘッダによる「no-cache」指定は、「proxy.config.http.cache.ignore_client_no_cache」パラメータを1にすることで無視できる。また、レスポンスヘッダの「no-cahce」指定は「proxy.config.http.cache.ignore_server_no_cache」パラメータを1にすることで無視できる。

キャッシュ条件や「新鮮さ」の判断基準を変更する

キャッシュを行うかどうかの判断や新鮮さの判断基準などは、records.configファイルなどで設定できるパラメータによって変更できる。関連するパラメータは多くあるが、主な物としては表1のものがある。

表1 キャッシュ設定に関連するパラメータ
スコープ パラメータ名 説明 指定できる値 デフォルト値
CONFIG proxy.config.http.cache.http INT キャッシュの有効/無効を設定 0(無効)、1(有効) 1
CONFIG proxy.config.http.cache.allow_empty_doc INT レスポンスボディのないレスポンスをキャッシュするかどうかを設定。Content-Lengthヘッダが指定されている場合のみ有効 0(キャッシュしない)、1(キャッシュする) 1
CONFIG proxy.config.http.cache.ignore_client_no_cache INT クライアントからのキャッシュバイパス要求を無視するかどうかを設定 0(無視しない)、1(無視する) 1
CONFIG proxy.config.http.cache.ignore_server_no_cache INT オリジンサーバーからのキャッシュバイパス要求を無視するかどうかを設定 0(無視しない)、1(無視する) 0
CONFIG proxy.config.http.cache.cache_responses_to_cookies INT Cookie付きのリクエストに対するレスポンスをキャッシュするかどうかを設定 0(キャッシュしない)、1(すべてをキャッシュ)、2(画像のみキャッシュ)、3(content-typeがtext以外のすべてをキャッシュ) 1
CONFIG proxy.config.http.cache.ignore_authentication INT WWW-Authenticationヘッダ付きのレスポンスをキャッシュするかどうかを設定 0(キャッシュする)、1(キャッシュせず、「WWW-Authentication」ヘッダを削除して無視する) 0
CONFIG proxy.config.http.cache.cache_urls_that_look_dynamic INT .aspで終わったり、「?」や「;」、「cgi」を含むURLに対するレスポンスをキャッシュするどうかを設定 0(キャッシュしない)、1(キャッシュする) 1
CONFIG proxy.config.http.cache.when_to_revalidate INT キャッシュされたコンテンツの「新鮮さ」の判定方法を設定 0(キャッシュ設定やヘッダの内容で判断)、1(ヘッダの内容でのみ判断)、2(常に新鮮でないものとする)、3(常に新鮮だとする)、4(0と同様だが、リクエストにIf-Midified-Since:ヘッダが存在する場合は必ずオリジンサーバーへの問い合わせを行う) 0
CONFIG proxy.config.http.cache.required_headers INT ヘッダに応じてキャッシュの挙動を変えるかどうかを設定 0(すべてのレスポンスは原則としてキャッシュ可能)、1(「Last-Modified」が設定されるか、「Expires」、「Cache-Control」ヘッダなどで明示的にキャッシュの持続時間が設定されたレスポンスの場合のみキャッシュ可能)、2(「Expires」、「Cache-Control」ヘッダなどで明示的にキャッシュの持続時間が設定されたレスポンスの場合のみキャッシュ可能) 2
CONFIG proxy.config.http.cache.max_stale_age INT Cache-Control:ヘッダのmax-ageパラメータでキャッシュが新鮮かどうかを判断する際に、キャッシュが新鮮でないとする最大期間を秒で設定する 604800
CONFIG proxy.config.http.cache.heuristic_min_lifetime INT 作成日や最終更新日でキャッシュが新鮮かどうかを判断する際に、新鮮であると判断する最小期間を秒で指定する 3600
CONFIG proxy.config.http.cache.heuristic_max_lifetime INT 作成日や最終更新日でキャッシュが新鮮かどうかを判断する際に、新鮮であると判断する最大期間を秒で指定する 86400
CONFIG proxy.config.http.cache.heuristic_lm_factor FLOAT 作成日や最終更新日でキャッシュが新鮮かどうかを判断する際に使用する係数 0.1

ここではすべてのキャッシュを無効化する設定や、Cookieが指定されたリクエストに対するレスポンスをキャッシュするかどうかといった設定を行える。これに加えて、前述したキャッシュの新鮮さを判断する際に使用するパラメータについてもここで設定が可能だ。

この中でも、特に注意したいのがCookie付きのリクエストに対するレスポンスをキャッシュするかどうかを決める「proxy.config.http.cache.cache_responses_to_cookies」パラメータだ。デフォルトの設定ではcookie付きのリクエストについてもキャッシュしてしまう可能性がある。この場合でも、前述の通りレスポンスヘッダによって特定のレスポンスについてはキャッシュしないよう設定できるのだが、Webアプリケーションなどが正しくこれらのヘッダーを出力するかどうか不安がある場合は、画像などのコンテンツのみをキャッシュするよう設定を変更しておくと良いだろう。

特定のURLに対し明示的にキャッシュを禁止する

リクエスト/レスポンスによるキャッシュ制御や設定ファイルによる包括的なキャッシュ設定に加えて、URL単位でキャッシュの有効/無効を設定することも可能だ。この設定は、「cache.config」ファイルで行える。

このファイルでは、次のフォーマットで設定を行うようになっている。

<primary_destination>=<値> <secondary_specifier>=<値> <パラメータ>=<値>

ここで、「primary_destination」はドメインやホスト名、IPアドレスなどを指定するもので、「secondary_specifier」はhttp/httpsやポート、URLのパスなどを指定するものだ(表2、3)。

表2 「primary_distination」に指定できるパラメータ
パラメータ名 説明
dest_domain ドメイン名
dest_host ホスト名
dest_ip IPアドレス
url_regex URLにマッチさせる正規表現
表3 「secondary_specifier」で指定できるパラメータ
パラメータ名 説明
port ポート番号
scheme スキーマ(httpもしくはhttps)
prefix URLのパス部分の接頭辞
subffix URLのパス部分の接尾辞
method リクエストメソッド(get、postなど)
time 時間(「08:00-14:00」のような形で指定)
src_ip クライアントのIPアドレス

また、「パラメータ」はprimary_distinationおよびsecondary_specifierで指定した条件にマッチしたリクエストに対しどういった処理を行うかを指定するものだ。ここでは以下のものが指定できる。

  • 「action」
  • 「cache-responses-to-cookies」
  • 「pin-in-cache」
  • 「revalidate」
  • 「ttl-in-cache」

まず「action」だが、これは条件にマッチしたリクエストについてキャッシュの挙動を変更するためのもので、値としては表4のものが指定できる。

表4 アクションとして指定できるパラメータ
パラメータ名 説明
never-cache キャッシュを行わない
ignore-client-no-cache クライアントからのリクエスト内の「Cache-Control: no-cache」ヘッダを無視する
ignore-server-no-cache サーバーからのレスポンス内の「Cache-Control: no-cache」ヘッダを無視する
ignore-no-cache クライアントからのリクエストおよびサーバーからのレスポンス両方の「Cache-Control: no-cache」ヘッダを無視する
cluster-cache-local クラスタの各ノードがローカルにキャッシュを保存することを許可する

たとえばその条件にマッチしたリクエストに対しキャッシュを行わせたくない場合、「action=never-cache」と指定すれば良い。

また、「cache-responses-to-cookies」はCookie付きのリクエストに対するレスポンスをキャッシュするかどうかを指定するものだ。records.config内の「proxy.config.http.cache.cache_responses_to_cookies」パラメータと同じく、0(キャッシュしない)、1(すべてをキャッシュ)、2(画像のみキャッシュ)、3(content-typeがtext以外のすべてをキャッシュ)のいずれかが指定できる。

そのほか、キャッシュを保持する(「pin」する)期間を指定する「pin-in-cache」、キャッシュが「新鮮」である期間を設定する「revalidate」、キャッシュの最大有効期間を設定する「ttl-in-cache」といったパラメータも指定できる。「pin-in-cache」パラメータや「revalidate」パラメータ、「ttl-in-cache」パラメータでは単位としてd(日)、h(時間)、m(分)、s(秒)が利用でき、「1h15m20s」のように混在した指定も可能だ。

Vary:ヘッダへの対応

WebサーバーやWebアプリケーションの設定によっては、たとえば言語を指定する「Accept-Language:」など、特定のリクエストヘッダに応じて出力が変わる場合がある。この場合、Webサーバーはレスポンスの「Vary:」ヘッダで出力に影響するヘッダの情報を出力することが推奨されているのだが、Traffic ServerでもこのVary:ヘッダの内容をチェックしてコンテンツを適切にキャッシュしたり、リクエストに対して適切なコンテンツを配信する仕組みが用意されている。この機能はデフォルトでは無効になっているが、表4のパラメータを変更することで有効にできる。

表4 「Vary:」ヘッダに応じたキャッシュを行う設定パラメータ
スコープ パラメータ名 説明 指定できる値 デフォルト値
CONFIG proxy.config.http.cache.enable_default_vary_headers INT Vary:ヘッダを参照して単一のURLに対し複数のキャッシュを保持するかどうかを設定 0(複数のキャッシュを保持しない)、1(複数のキャッシュを保持する) 0
CONFIG proxy.config.http.cache.vary_default_text STRING テキストコンテンツについて、ここで指定したヘッダに対してのみ、複数のキャッシュの保持を有効にする ヘッダ名 なし
CONFIG proxy.config.http.cache.vary_default_images STRING 画像コンテンツについて、ここで指定したヘッダに対してのみ、複数のキャッシュの保持を有効にする ヘッダ名 なし
CONFIG proxy.config.http.cache.vary_default_other STRING テキスト/画像以外のコンテンツについて、ここで指定したヘッダに対してのみ、複数のキャッシュの保持を有効にする ヘッダ名 なし
CONFIG proxy.config.cache.limits.http.max_alts INT 1つのURLに対しキャッシュできる最大数を指定する 最大数 5

たとえばオリジンサーバーが「Accept-Language:」ヘッダの値によって異なるコンテンツを返す場合、「proxy.config.http.cache.enable_default_vary_headers」パラメータを1に設定し、「proxy.config.http.cache.vary_default_text」に「Accept-Language」を設定することで、同一のURLに対しAccept-Language:ヘッダの内容に応じた複数のキャッシュを保持させることが可能になる。

そのほかにも多数の設定が可能

今回は主にキャッシュ関連の設定について紹介したが、これ以外にもTraffic Serverには多数の設定項目が用意されている。また、プラグインで機能を強化したり、クラスタ構成を取ることも可能だ。これらはドキュメントの管理者ガイド設定ファイルリファレンスで詳しく説明されているので、そちらを参照すると良いだろう。