suin.io

Cache-Controlヘッダのmax-ageとs-maxageの違いと使い道

suin2016年7月25日

Cache-ControlヘッダはHTTP/1.1の仕様RFC2616で定義されているヘッダで、レスポンスのキャッシュをクライアントがどのように扱ったら良いかを指示するものです。例えば、Cache-Control: no-cacheは「クライアントはレスポンスをキャッシュするな」という意味になります。

Cache-Controlヘッダにはpublic, private, no-cacheなど様々なディレクティブがあり細かく指示ができるのですが、その中でよく似たディレクティブにmax-ages-maxageがあります。どちらもキャッシュの有効期限を指定するものですが、この2つはどのように違うのでしょうか?また、どのような使い道があるのでしょうか?

「私用キャッシュ」と「共有キャッシュ」

HTTPのキャッシュは大きく分けて私用キャッシュ(private cache)共有キャッシュ(shared cache)の二種類があります1私用キャッシュというのは、ブラウザのキャッシュと言えばすぐイメージがわくのではないでしょうか?私用キャッシュはクライアントに保存されるもので、他のクライアントと共有されないキャッシュです。特に何も言わずに「キャッシュ」と言うときはこの私用キャッシュを指すことが多いかと思います。

クライアントに保存される私用キャッシュ

HTTPのオーソドックスなイメージを考えると、サーバがありクライアントがあり、クライアントのリクエストに応じてサーバがレスポンスを返すといった具合に、登場人物はサーバとクライアントの二者を想像することが多いと思います。

実際のHTTPでは、クライアントのリクエストを受け取り、サーバに同じようなリクエストを投げる中継者が登場することがあります。もう少し具体的に言うと、学内や社内の構内HTTPプロキシがその代表です。構内プロキシは、構内のHTTP通信がインターネットに出て行く手前で構え、外部サーバとの通信を一旦受け止めます。

かなりざっくりとした説明ですが、構内プロキシは、ウイルスチェック・許可しないサイトへのアクセス遮断といったセキュリティ向上を担うのも1つの役割です。もう1つの役割は、通信速度の向上にあります。構内からサイトAにアクセスがあったとき、サイトAのコンテンツをプロキシのキャッシュに保存しておき、また構内の別の端末からサイトAに全く同じアクセスがあった場合、プロキシはサイトAに問い合わせることなく、自分が持っているキャッシュから構内の別端末にレスポンスを返します。こうすることで、通信が完結するので通信速度が早くなるわけです。

この説明でもうお気づきかと思いますが、HTTPのキャッシュは中継者が持つ場合があるのです。こうした中継者が持つキャッシュのことを共有キャッシュと呼びます。

クライアントに保存される私用キャッシュとプロキシに保存される共有キャッシュ

max-ages-maxageの違い

私用キャッシュと共有キャッシュの2つがあることが分かったので、Cache-Controlの話に戻りますが、まさにmax-ages-maxageはこの2つのキャッシュに関係しています。

max-ageは私用キャッシュ・共有キャッシュ向けのキャッシュの寿命を指定するディレクティブです。従って、Cache-Control: max-age=60といったヘッダをレスポンスに含めると、ブラウザも中継者たるプロキシも基本的にそのレスポンスを60秒間保存します。

一方で、s-maxageディレクティブは共有キャッシュ向けにキャッシュの寿命を指定するものです。しかし、クライアントには影響しません。つまり、Cache-Control: s-maxage=60をセットすると、構内プロキシなどは60秒間は自分のキャッシュからクライアントにレスポンスを返しますが、クライアントはキャッシュを作らず都度プロキシに問い合わせるようになります。

max-ageは私用・共有どちらにも効くわけですが、Cache-Control: s-maxage=200, max-age=60と設定した場合どうなるでしょうか?この場合、クライアントは60秒間キャッシュを使いますが、プロキシなどの中継者は60秒間を指定したmax-ages-maxageに上書きされ、200秒間キャッシュを保持するようになります。

Cache-Controlのmax-age, s-maxageとクライアント・プロキシの振る舞い

CDNも中継者の1つ

最近では静的ファイルなどを高速かつ安定的に配信できるように最適化されたネットワークを実現するCDN(Contents Delivery Network)というものがあります。CDNを使うと、ウェブサイトの負荷分散ができたり表示速度が高速になったり、トラフィックの多いサイトには大きな恩恵があります。

先ほどHTTPの中継者には構内プロキシがあると言いましたが、CDNも中継者の1つになります。クライアントはCDNのサーバにファイルを要求すると、CDNはバックエンドにあるウェブサーバにファイルを要求するといったように、CDNを導入したウェブサイトにもプロキシのようにHTTP通信のリレーがあるのです。

s-maxageはCDNにキャッシュの寿命を伝えるときに使える

CDNも中継者の一種ですから、s-maxageを使うとCDNだけにキャッシュの有効期限を指示することができます。CDNでまず有名なのといえば、AWSのCloundFrontですが、これもs-maxageを見ており、Cache-Controlmax-ages-maxageがある場合、s-maxageの値を見てくれます2。DDoS攻撃にも強いことで知られるCloundFlareも同様の仕様になっています3。つまり、CDNを使うにあたって、s-maxageを上手に設定してあげると、バックエンドサーバへの負荷を抑えつつ、クライアントにCDNに常に最新のリソースが同期されていないかリクエストをさせる、といったことができるようになります。

まとめ

HTTP 1.1におけるCache-Controlmax-ages-maxageの違いについて取り上げました。max-ageは私用キャッシュ・共有キャッシュ向けのキャッシュの有効期限を指定するもので、s-maxageは共有キャッシュ向けの有効期限です。CDNを使っているサービスではs-maxageをうまく活用することで、バックエンドサーバへの負荷は抑えつつも、クライアントにはCDNのキャッシュ寿命よりも短い頻度で問合せさせる、といったことができるようになります。


  1. private cache→私用キャッシュ、shared cache→共有キャッシュの訳語はRFC7234邦訳による。 

  2. Specifying How Long Objects Stay in a CloudFront Edge Cache (Expiration) - Amazon CloudFront参照。 

  3. How Do I Tell CloudFlare What to Cache? – CloudFlare Support参照。 

RELATED POSTS