はじめに
以前の個人開発で「S3のファイル到着を複数待ってから処理を開始したい」といったケースがありました。
現状のイベントを扱うAWSサービスでは1イベント-1トリガが基本であり、イベントの待ち合わせを実現することが難しいです。
lambdaやEC2で継続起動してセッションキープして管理することも可能ではありますが、到着を待つだけのリソースとしてはコストが大きいです。
そこでAWSサービスを組み合わせて、以下の要件を満たせるような方法を検討しました。
- S3の複数ファイルの到着を待ち合せて、必要なファイル全てが到着をしたことをトリガに後続処理が動くこと
- 到着ファイルが連携されるタイミングは決まっておらず、いつ到着するかはわからない
- コストや無駄リソースを極力抑える
アーキテクチャ
以下のようなステップを踏む想定です。
- Objectの到着イベントEventBridgeでキャッチします。
- キャッチしたイベントはCloudWatch logsのログストリームに送信し、メトリクスフィルタでオブジェクトのキーを指定します。
- メトリクスフィルタによって定義したメトリクスに対して複合アラームを設定し、複数のファイル到着を管理します。
- アラートが発せられた時にはイベントが出るため、これをEventBridge等でキャッチし、後続処理を開始する。
実装方法
S3でEventBridgeへのイベント通知をONにする
S3イベントはデフォルトでEventBridgeへのイベント通知がOFFになっているため、S3の設定を修正する必要があります。
EventBridgeでPutObjectに対してイベント設定
S3のオブジェクト到着イベントをキャッチするために以下のようなイベントパターンを設定していきます。
{
"source": ["aws.s3"],
"detail-type": ["Object Created"],
"detail": {
"bucket": {
"name": ["<YOUR BUCKET NAME>"]
}
}
}
イベントが到着したときのターゲットにはCloudWatchを設定します。
ロググループは新規作成することも、既存のロググループを選択することも可能です。
CloudWatch ログストリームににメトリクスフィルターを設定
特定のオブジェクトのキーに対してフィルタをするため、JSON構造の中から以下のようにフィルタパターンを設定します。
{ $.detail.object.key = "任意の値(ファイル名等)" }
構文を編集する際には以下を参照のこと。
CloudWatch アラームの設定
前段で設定した各メトリクスに対して、それぞれアラームを作成していきます。
以下のように条件として、1カウント以上記録したときにアラートをあげるように設定していきます。
設定したアラームを複数選択し、複合アラームを作成します。全てAND
で繋いでいきます。
この設定により、すべてのアラートが上がった時、すなわちすべてのS3ファイルが到着したときにアラートが上がるようになります。
後続処理
アラームを発したときにはイベントが飛ぶので、それをEventBridgeでキャッチしてあげることで後続の処理のトリガにすることができます。
{
"source": [
"aws.cloudwatch"
],
"detail-type": [
"CloudWatch Alarm State Change"
],
"resources": [
"arn:aws:cloudwatch:<REGION>:<YOUR ACCOUNT ID>:alarm:<YOUR ALARM>"
]
}
おわりに
以上が待ち合わせて後続をトリガする方法でした!
期間やデータポイントを調整することで、どれだけのファイル到着間隔を許容するのかを設定することが可能になります。
ただアーキテクチャとして回りくどくなってしまったので、複数のイベントの待ち合わせがStepFunctionsだけでできるようになると嬉しいなぁと思います...