ウェブキャッシュ(Web cache)とAWS S3、CloudFront

2024-08-21 hit count image

ウェブ開発におけるキャッシュ(Cache)について説明をして、AWS S3とCloudFrontを使って静的ファイルでウェブサービスを提供する際にキャッシュを適用する方法について説明します。

概要

ウェブ開発においてキャッシュ(Cache)は重要な役割を果たします。キャッシュを通じてウェブサービスのパフォーマンスを向上させることができ、ユーザーエクスペリエンスを改善することができます。今回のブログポストでは、ウェブ開発におけるキャッシュ(Cache)について説明をして、AWS S3に静的ファイルでウェブサービスを提供する際にキャッシュを適用する方法について説明します。

ウェブキャッシュの誕生背景

クライアント(PC、スマートフォン)からサーバーにある情報を取得するためにはインターネット(Internet)を使います。

Web cache and S3 - server and client with internet

クライアントとサーバーを接続するインターネットは物理的に接続されており、世界中のインターネットは海底ケーブルで接続されています。

Web cache and S3 - internet submarine cable

クライアントとサーバーはこのように物理的に接続されているため、もちろん距離が遠いほどデータの送受信に時間がかかることになります。

ウェブキャッシュ

ウェブキャッシュは物理的に遠い場所にあるサーバーのコンテンツのうち、変更が少ないコンテンツ(静的コンテンツ: HTML、CSS、JS、画像、ビデオなど)を物理的に近い場所(サーバー)にコピーして配置することでデータの送受信の遅延を減らす技術です。

Web cache and S3 - web cache

ウェブでは大きく3つのキャッシュを使用します。

  1. CDN(Contents Delivery Network)
  2. ブラウザキャッシュ(Browser cache)
  3. データベースキャッシュ(Database cache)
Web cache and S3 - web cache with browser

今回のブログポストではCDNとブラウザキャッシュについて説明します。

CDN(Contents Delivery Network)

CDNは変更が少ないコンテンツのコピーを世界中の複数の場所にあるサーバーに配置してコンテンツを提供するサービスです。

これを通じてクライアントとサーバー間の距離を縮めてデータの送受信の遅延を減らすことができます。

例えば、世界的に有名なCDNサービスであるCloudflareは次のように世界中にサーバーを置いています。

Web cache and S3 - cloudflare server list

Cloudflareを利用すると静的ファイルをCloudflareが提供するサーバーにコピーしてクライアントと近いサーバーからコンテンツを提供することができます。

ブラウザキャッシュ(Browser cache)

クライアント側から見ると最も近いサーバーはクライアント自体です。ブラウザはクライアントが一度アクセスしたサイトから一部のコンテンツをクライアントストレージに保存して再度アクセスする際にこの保存されたコンテンツを使えるようにするブラウザキャッシュ機能を提供します。

Chromeブラウザの場合次の場所にキャッシュをします。

  • Windows: C:\Users\<User Name>\AppData\Local\Google\Chrome\User Data\Default\Cache
  • macOS: /Users/<User Name>/Library/Caches/Google/Chrome/Default/Cache

ウェブキャッシュの動作方法

ウェブキャッシュがどのように動作するかについて説明します。

Web cache and S3 - web cache process
  1. ユーザーがブラウザからサービスにアクセスします。
  2. ブラウザはブラウザにキャッシュされたものがあるか確認し、キャッシュがある場合はそれを使って画面を表示します。
  3. ブラウザにキャッシュがない場合はCDNにキャッシュがあるか確認します。CDNにキャッシュがある場合はそれを使います。
  4. CDNにキャッシュがない場合は実際のサーバーからコンテンツを取得します。
  5. このときCDNはキャッシュをする必要があるかどうかを確認し、キャッシュできる場合はキャッシュします。
  6. ブラウザも同様にキャッシュできる場合はキャッシュします。
  7. 次からユーザーが同じコンテンツにアクセスする時、ブラウザとCDNでキャッシュされたコンテンツを使います。

ウェブキャッシュの設定

ブラウザとCDNはどの基準でキャッシュを設定するでしょうか?ブラウザとCDNはHTTPレスポンスヘッダーにあるExpiresCache-ControlEtagLast-Modifiedなどを確認してキャッシュを設定します。

HTTPレスポンスヘッダーにキャッシュを設定する方法は次のようになります。

  • Nginxの設定
server {
    listen 80;
    server_name example.com;

    location / {
        # Set Cache-Control
        add_header Cache-Control "max-age=3600, public";

        # Set Expires
        expires 1h;
    }
}
  • ウェブサーバーの設定(NodeJSのExpress例)
const express = require('express');
const app = express();

app.use((req, res, next) => {
    // Set Cache-Control
    res.setHeader('Cache-Control', 'max-age=3600, public');

    // Set Expires
    const maxAgeInSeconds = 3600;
    const date = new Date();
    date.setSeconds(date.getSeconds() + seconds);
    const expiryDate = date.toUTCString()
    res.setHeader('Expires', expiryDate);

    next();
});

app.get('/', (req, res) => {
    res.send('Hello World!');
});

app.listen(3000, () => {
    console.log('Server is running on port 3000');
});

このように設定されたHTTPレスポンスヘッダーを確認してCDNとブラウザがキャッシュを設定します。

AWS S3とCloudFront

AWSのS3とCloudFrontを使って静的ウェブサイトを提供することができます。

  • S3(Simple Storage Service): 静的ファイルを保存するサービス
  • CloudFront: CDNサービス

S3はストレージサービスですが、静的ファイルでウェブサービスを提供するサーバー機能も提供しています。

一般的にHTML、CSS、JavaScriptで開発された静的ウェブページやReact、Vue、Angularなどのフロントエンドフレームワークで開発されたウェブアプリケーションのビルド結果をS3にアップロードしてCloudFrontを通じてサービスします。

Web cache and S3 - AWS S3 and CloudFront cache

この時、S3にアップロードしたファイル設定を通じてブラウザキャッシュとCDN(CloudFront)キャッシュを設定することができます。

AWS S3キャッシュ設定

キャッシュはHTTPのレスポンスヘッダーにExpiresCache-Controlを設定するため、基本的にフロントエンド側で設定することはできません。

CloudFront + S3はサーバーがないためHTTPヘッダーを設定するサーバーコードを追加することはできません。

しかし、S3がサーバー機能を持っているため、S3の設定を通じてキャッシュを設定することができます。

AWSが提供するCLIツールを使ってS3にファイルをアップロードする際、次のようなコマンドを使います。この時、--cache-controlオプションを使うことでキャッシュを設定することができます。

aws s3 cp <Target directory> s3://<S3 Bucket name> --recursive --exclude "assets/*" --cache-control 'public,max-age=60,stale-while-revalidate=2592000’
  • Target directory: S3にアップロードするビルド結果があるローカルフォルダのパス
  • S3 Bucket name: ファイルをアップロードする対象となるS3のBucket名
  • --recursiveオプション: aws s3 cpは基本ファイル1つをコピーするコマンドなので、指定されたディレクトリのすべてのファイルをアップロードするために--recursiveオプションを使います
  • --exclude "assets/*": アップロード除外対象の設定
  • --cache-control 'public,max-age=60,stale-while-revalidate=2592000': キャッシュ設定
    • max-age=60: 60秒間キャッシュ
    • stale-while-revalidate: max-ageによってキャッシュが終了した場合、バックグラウンドでコンテンツを再確認してキャッシュする間、期限切れのキャッシュを最大30日間提供するように設定

GitHub Actions

次はGitHub Actionsを使ってS3にファイルをアップロードするコードです。

- name: Configure AWS credentials
  uses: aws-actions/configure-aws-credentials@v4
  with:
    role-to-assume: $
    aws-region: ap-northeast-1
- name: Upload file to S3
  run: |
    aws s3 rm s3://$ --recursive
    aws s3 cp apps/dist s3://$ --recursive --exclude "assets/*" --cache-control 'public,max-age=60,stale-while-revalidate=2592000'
    aws s3 sync apps/dist/assets s3://$/assets --cache-control 'public,max-age=60,immutable'

aws s3 rmを使ってすべてのファイルを削除した後、aws s3 cpを使ってファイルをアップロードします。最後にassetsフォルダをaws s3 syncを使ってアップロードします。

stale-while-revalidateを使った無中断デプロイ

AWSのブログで紹介された使い方です。

stale-while-revalidateを使うと中断なしにサービスバージョンを更新することができます。

Web cache and S3 - stale-while-revalidate option for no downtime deployment
  1. ユーザーがブラウザでサービスを実行します。
  2. V1で既にサービスを利用しているユーザーは、ブラウザにstale-while-revalidateが設定されたV1のキャッシュがあるため、それを優先して使います。
  3. ブラウザはバックグラウンドでキャッシュが終了した(max-age)コンテンツをCloudFront(CDN)に要求します。
  4. CloudFrontはV2に更新されたキャッシュがあるため、それをブラウザに提供します。
  5. ブラウザはCloudFrontから受け取ったコンテンツをキャッシュして次からこれを使います。
  6. もし、CloudFrontのキャッシュも更新が必要な場合(max-age)、まずはstale-while-revalidateが設定されたV1のキャッシュをブラウザに提供した後、バックグラウンドで実際のサーバーからコンテンツを取得して自身のキャッシュを更新します。

完了

これでウェブキャッシュ(Web cache)について説明をして、AWS S3とCloudFrontを使って静的ファイルでウェブサービスを提供する際にキャッシュを適用する方法について説明しました。

このブログポストがウェブキャッシュの理解とAWSでウェブキャッシュを適用する際に役立つことを願います。

私のブログが役に立ちましたか?下にコメントを残してください。それは私にとって大きな大きな力になります!

アプリ広報

今見てるブログを作成たDekuが開発したアプリを使ってみてください。
Dekuが開発したアプリはFlutterで開発されています。

興味がある方はアプリをダウンロードしてアプリを使ってくれると本当に助かります。

Posts