AWSにはS3やCloudFrontという良いものがあり、サーバーを持たぬ者でも静的コンテンツを大規模に効率良く配信する事が可能です。
S3は大容量のコンテンツサーバー、CloudFrontは多拠点型のキャッシュサーバーで、共にAWSのサービスです。
一昔前はこのような事ができるのは一部の人間に限られており、良い世の中になったなあと思います。
S3とCloudFrontで静的コンテンツを扱うと、コンテンツ更新時のキャッシュコントロールに難しさがあります。
「新しくファイルアップロードしたのに、なんでヒョージ変わらへんねん」というアレです。
CloudFrontのキャシュの生存期間はコントロール可能で、TTLの設定を変えてみたり、AWSのコンソールでキャッシュの削除(invalidation)したり。
色々方法はありますが「コンテンツが更新されたら、キャッシュも更新される」をLambdaで自動化できるっぽいのでやってみました。
Lambdaとは
Lambda(ラムダ)を使うと、AWSで起こる色々なイベントを起点にプログラマが書いたプログラムを実行する事ができます。
プログラム実行に使うコンピュータをプログラマが意識する必要は無く、むきだしのサーバーはAWSに隠蔽されている事から「サーバレス○○」だ!と呼ぶ人もいます。
Lambdaはトリガー的に使えるので、invalidateを自動化するプログラムを書けばなんとかなりそうです。
ロールの作成
Lambdaの実行とCloudFrontの操作が必要になるので、これが可能なロールをIAM(権限コントロール)から作成しておきます。
Lambdaの実行権限から
ラムダ基本実行権とCFへのフルアクセスを選択します。
こんなかんじのロールができればオッケーです。
LambdaFuntionの設定
AWSコンソールからLambdaFunctionの作成へと進みます。
BluePrint(一般的な利用用途のテンプレ)を使わずに「Configure triggers」に進みます。
AWSのどのサービスでどのような状態変化が起こった場合にトリガーを発動するのか、を設定します。
ここではS3を選択します。
「furyu-sandbox」というS3バケットに「拡張子がjpgのファイルが作られた(Object Created(All))」場合の設定はこんなかんじです。
いよいよラムダ関数の登録です。
実行環境はPython2.7を選択します。
コードは下記をそのままコピペして、XXXXXXXXXXの箇所をCFのディストリビューションIDに書き換えます。
from __future__ import print_function import boto3 import time def lambda_handler(event, context): for items in event["Records"]: path = "/" + items["s3"]["object"]["key"] print(path) client = boto3.client('cloudfront') invalidation = client.create_invalidation(DistributionId='XXXXXXXXXX', InvalidationBatch={ 'Paths': { 'Quantity': 1, 'Items': [path] }, 'CallerReference': str(time.time()) })
print()された文字列は、CloudWatchでログとして出力されます。(後述)
先ほど作成したロールを選択します。
こんなかんじになります。
作成したLambdaFunctionの実行とモニタリング
ファイルS3バケットにアップロードし、反応を観察してみます。
S3へのファイルのアップロード後、作成したFunctionを選択して「Monitoring」タブを選択します。
LambdaFunctionの実行状況が確認できます。
「View Logs in Cloud Watch」で、詳細なログを確認できます。
printの内容やエラーもここに出力されます。
CloudFrontの対象ディストリビューションのInvalidationsタブにInProgressが見えます。
キャッシュ削除が起動された事が確認できます。
「雲の上のクラウドに向かってラムダ式を唱えると全ては計算された。サーバーから開放された人々は最も人らしくなった」
ミステリアスなイメージを持つラムダですが、利用用途は無限、うまく使うとAWSと仲良くする事ができます。
日宇