0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【CloudFront】キャッシュ設計指針を整理してみる

Posted at

想定読者

CloudFrontの役割、目的は理解している人。
キャッシュポリシーをなんとなくで決めてしまっている人。

キャッシュヒットのしくみ

image.png

ビューワーリクエスト(ユーザからのリクエスト)のがエッジロケーションに到達すると、リクエスト内容に紐づいたキャッシュキーを生成します。

一方、エッジロケーションが保持するキャッシュ内の各オブジェクトにも、固有のキャッシュキーが払い出されます。

つまり、リクエストから生成されるキャッシュキーと、エッジロケーションが保持するキャッシュオブジェクトのキャッシュキーが一致するかどうかで、キャッシュヒットの発生有無が変わるということになります。

このキャッシュヒット率を高めるために、キャッシュキーに含める要素をどのように設計していくかが重要になります。

キャッシュ設計

デフォルトでは以下の要素に基づき、キャッシュキーが生成されます。

  • ディストリビューション名
  • オブジェクトパス

リクエストパスごとにキャッシュを生成するシンプルな方法です。

キャッシュキーに含む要素を追加で管理するには、キャッシュポリシーを利用します。
image.png
リクエストヘッダ、クエリ文字列、cookieごとに含める要素を指定します。
上記で対応できない複雑なユースケースでは、別途Lambda@Edgeを用いてカスタマイズするとよいでしょう。

1.リクエストヘッダ

ユーザのデバイスタイプや場所、ヘッダー構造等リクエストの特性に応じてキャッシュ設計する場合に利用します。
主な要素は以下の通り。

  • デバイスタイプ
# ヘッダ 判断条件
1 CloudFront-Is-Android-Viewer AndroidOSからのリクエストであるか
2 CloudFront-Is-IOS-Viewer IOSからのリクエストであるか
3 CloudFront-Is-Desktop-Viewer デスクトップからのリクエストであるか
4 CloudFront-Is-Mobile-Viewer モバイルからのリクエストであるか
5 CloudFront-Is-SmartTV-Viewer スマートTVからのリクエストであるか
6 CloudFront-Is-Tablet-Viewer タブレットからのリクエストであるか
  • 場所
# ヘッダ 判断条件
1 CloudFront-Viewer-City ビューワーの市区町村名
2 CloudFront-Viewer-Country-Name ビューワーの国名
3 CloudFront-Viewer-Country-Region ビューワーのリージョンを表すコード
4 CloudFront-Viewer-Country-Region-Name ビューワーのリージョン名
5 CloudFront-Viewer-Latitude ビューワーのおよその緯度
6 CloudFront-Viewer-Longitude ビューワーのおよその経度
7 CloudFront-Viewer-Metro-Code ビューワーのメトロコード(米国のみ)
8 CloudFront-Viewer-Postal-Code ビューワーの郵便番号
9 CloudFront-Viewer-Time-Zone ビューワーのタイムゾーン
  • その他
# ヘッダ 判断条件
1 CloudFront-Forwarded-Proto ビューワーのリクエストのプロトコル
2 CloudFront-Viewer-Http-Version ビューワーのリクエストのHTTPバージョン
3 Accept ビューワーの理解できるデータ形式
4 Authorization 認証情報とメカニズム
5 Host 送信先のホスト名とポート番号
6 Origin オリジンのホスト名とポート番号
7 Referer 現在リクエストされているページへのリンク先を持った直前のウェブページのアドレス
8 Access-Control-Request-Method 実際のリクエストを行う前にブラウザが送信する事前フライトリクエストに含まれる。ブラウザが実際のリクエストで使用するHTTPメソッドをサーバーに伝えるためのもの
9 Access-Control-Request-Headers 実際のリクエストを行う前にブラウザが送信する事前フライトリクエストに含まれる。ブラウザが実際のリクエストで使用するHTTPヘッダーをサーバーに伝えるためのもの

2.クエリ文字列

クエリ文字列をキャッシュキーに含めるかを設定できます。
クエリ文字列を明示的に指定して含めることも可能です。

3.cookie

考え方はクエリ文字列同様。

キャッシュ設計指針

設計をする際は以下の二点を考慮すべきかと思います。

  • キャッシュキーに含める要素は最小限に
    関係のない要素をキャッシュキーに含めてしまうと、同じオブジェクトに対し複数のキャッシュキーを生成することになります。

  • アプリケーションの仕様をきちんと理解する
    要素を最小限にすると言えど、必要な要素を逃してしまっては元も子もありません。

例として、CloudFront+API Gateway+Lambdaから構成されるバックエンドを考えます。
Lambdaは、クエリ文字列を表示する、シンプルなものとします。

export const handler = async(event) => {
    const query = event.queryStringParameters.testQuery;

    const response = {
        statusCode: 200,
        body: `クエリ文字列は${query}です。`,
    };
    return response;
};

この時以下の通り、キャッシュポリシーにクエリ文字列を含めていればアプリケーションは意図した通りに動きます。
image.png
きちんと動きます。もちろん初めて指定するクエリ文字列の値に対しては該当するキャッシュキーが存在しないので「Miss From CloudFront」となります。
image.png
image.png

続いてキャッシュポリシーからクエリ文字列を除いてみます。
image.png
前述した通り、デフォルトで指定されるURLパスによってのみキャッシュされるため、クエリ文字列の値を変更したとしてもレスポンスには反映されません。(意図しないキャッシュオブジェクトがレスポンスされます。)

検証環境では、クエリ文字列指定しない状態でキャッシュを作成しているためか、クエリ文字列の値を変更しても、そもそもエラーとなりました。
image.png

さいごに

キャッシュ設計次第でアプリケーションの意図しない動作を誘発してしまうため、アプリケーションチームとの連携の重要性がいかに重要か再認識できました。
リクエストボディの内容もキャッシュキーに含める場合は、Lambda@Edgeにて処理する必要があるのだろうか。。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?