Help us understand the problem. What is going on with this article?

AWS CloudFrontの配信元のファイル(S3)が更新されたら自動的にキャッシュをクリアする仕組みを作る

こまった事

こんな感じのアプリ構成で
image.png
CloudFront経由でS3に格納したコンテンツを配信する場合、
CloudFrontのCloudFrontエッジロケーション(キャッシュサーバー)からコンテンツをクライアントに配信する為、
クライアントに中々、最新のコンテンツが行き渡らない事象がしばしば発生します。

CloudFrontにキャッシュを残さないようにすれば?

設定次第でそれもできますが、
それだとCloudFrontの意味ないです。
それと毎回、配信元のS3にアクセスしに行く事になるのでS3のアクセス数が増加してしまいます。(お金がかかってしまう)

解決方法

CloudFrontの配信元のファイル(S3)が更新されたら自動的にCloudFrontのキャッシュをクリア(Invalidation)してあげる仕組みを作ります。

配信するファイルにもクライアントにキャッシュさせないようにメタ情報を付与します。
方法はこちらの記事を参考に
https://qiita.com/anchoor/items/2dc6ab8347c940ea4648

その仕組みどんな風に作るの?

配信元のファイル(S3)の更新をトリガーとして実行するLambdaFunctionを作成します。
そのLambdaFunction内でCloudFrontのキャッシュをクリア(Invalidation)してあげます。

このように作るのだ

image.png
S3のオブジェクトの更新をトリガーとして発火する
LambdaFunctionを作成します。

※詳細は、こちらの記事で記載しています。
AWS S3のオブジェクトの更新をトリガーとして発火する LambdaFunctionを作成する

LambdaFunctionの中身

今回はGoで書きました。
AWSのAPI(AWS SDK for Go)にCloudFrontののキャッシュをクリア(Invalidation)するAPIがあるので
そいつをキックしてあげるだけです。
https://docs.aws.amazon.com/sdk-for-go/api/service/cloudfront/#CloudFront.CreateInvalidation

※詳細は、こちらの記事で記載しています。
AWS S3バケット名からCloufFrontのキャッシュをクリア(CreateInvalidation)するAPIをコールする

実装に苦労した点

ロール周りや、パーミッションの問題で実際に動作させるまで時間がかかりました。
これはエラーメッセージが丁寧に出力されるので一つ一つ対応していけば問題ないのですが、

S3オブジェクトの更新トリガーについはそうもいきませんでした。
私はS3バケットの中全てのオブジェクトを更新チェック対象としている為、
オブジェクト更新したら更新した数のオブジェクトの数分、発火してしまいます。

つまり、対象のS3バケットの中身20個のファイルを格納、更新したら20回発火します。

苦労した点の対応

Goの実装内でAPI(CloudFront.CreateInvalidation)実行時に一意なIDを指定します。
そのIDには現在年月日時分秒を指定していましたが、
それを現在年月日時分を指定する事で1分に一回しかCreateInvalidationを実行しないようにしました。イベント発火の最初の1回のみ実行され、後の発火は全てIDが重複している為、エラーとなりますので1分に1回しか実行されません。

よって、S3バケットの中身20個のファイルを格納、更新したら20回発火しますが、1回だけ正常にCreateInvalidationを実行し、19回はエラーとなります。

所感

これでクライアントは常にCloudFrontエッジロケーション(キャッシュサーバー)を見に行き、見にいく先のCloudFrontエッジロケーション(キャッシュサーバー)は最新のコンテンツが行き渡っています。

CloudFront標準の機能で用意してくれててもいいような気がする機能でした。

この機能を実装した直後にこんな記事が...
「【朗報】Amazon CloudFrontのキャッシュ削除(Invalidation)が速くなりました【5秒で90%】」
https://dev.classmethod.jp/cloud/aws/cloudfront-fast-invalidation/

※構成図はこちらの記事を参考にして作成しました。
https://qiita.com/nave-m/items/68425f476b254a1a47b0

Shi-nakaya
パッケージ開発ベンダーで社内の何でも屋から脱出した人が 日々の中でつまった事、ハマった事を書いています。 現在は、クラウドベンダーの自社サービス部門で開発を担当しています。 業務で使用している言語はjs(React)、Go、Java インフラはAWSを使用
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした