はじめに
こんにちは、技術3課の紅林です。前回は、AWS Data PipelineでSlackの全チャンネルの1日分メッセージの取得を自動化する試みをご紹介しました。今回は、AWS Step Functions(以下、Step Functions)を使って、同様のことをしてみたいと思います。
AWS Step Functionsについて
まず、Step Functionsの概要を公式サイトから引用します。
AWS Step Functions により、視覚的なワークフローを使用して、分散アプリケーションとマイクロサービスのコンポーネントを簡単に調整できます。(略)
AWS サーバーレスプラットフォームの一部で、AWS Lambda 関数のサーバーレスアプリケーション向けの調整を簡単にします。Step Functions は、Amazon EC2 や Amazon ECS といったコンピューティングリソースを使用したマイクロサービスの調整にも使えます。
AWS Step Functions (分散アプリケーションとマイクロサービスの構築)
LambdaファンクションやEC2インスタンスのアプリケーション等を組み合わせて、シーケンシャル、分岐、並列等、処理のフローを設計/管理が可能です。
今回想定するSlackの全チャンネルの1日分メッセージの取得する処理は、この記事で言及した通り、約1500秒要すると想定されます。
したがって、タイムアウト値5分が限界の単一のLambdaファンクションでは処理の完了が難しいため、(LambdaファンクションだけでLambdaファンクションを複数つなげることも出来ますが)複数のLambdaファンクションをStep Functionsを用いることにより構成し、処理を完遂させます。
構成/処理の流れ
構成/処理の流れは以下の通りとなります。
①Cloud Watch Eventsが設定されたスケジュールでStep Functionsを実行します。
②Step Functionsがワークフローに従って、Lambdaを実行します。
③LambdaがSlackのデータを取得します。
④取得したデータをS3に保存
ワークフロー
今回のワークフローのイメージは以下の通りとなります。
Step Functionsでは、シーケンシャルステップ、パラレルステップ、分岐パス (選択)、タイマー (待機) 等をワークフローのステップとして定義できます。
今回は、Slackのチャンネルからメッセージを取得する単一のLambdaファンクションを繰り返し実行し、全てのチャンネルからメッセージの取得が完了したら処理を完了とします。
Lambdaファンクションの実行後に全てのチャンネルのメッセージを取得済か判定(分岐)し、まだ取得していないチャンネルがあった場合には再度Lambdaファンクションを実行します。
Lambdaファンクション
Lambdaファンクションの処理の流れは以下の通りとなります。
0. 前回実行のLambdaファンクションから、メッセージ取得済みチャンネルの情報をパラメータで取得
1. Slackの全チャンネルリストを取得
2. 「0」で受け取った情報から、メッセージ未取得のチャンネル(一定数)のメッセージを取得
3. 「2」の結果、全てのチャンネルのメッセージの取得が完了すれば終了。完了しなければ、取得済のチャンネルの情報をパラメータで渡し「0」に戻る。
ハマりどころ
当初チャンネルのリストを取得するLambdaファンクションとチャンネルのメッセージを取得するLambdaファンクションを別々に実装し、取得したチャンネルのりスト情報をチャンネルのメッセージを取得するLambdaファンクションにパラメータで渡す方法を検討していました。
しかしながら、以下の通り、全チャンネル分のリストの情報が、パラメータの受け渡しのサイズ制限に引っかかってしまい、受け渡すことができなかったため、上記のように都度チャンネルのリストを取得する実装としています。
Maximum input or result data size for a task, state, or execution
32,768 characters. This limit affects tasks (activity or Lambda function), state or execution result data, and input data when scheduling a task, entering a state, or starting an execution.
Limits - AWS Step Functions
手順
以下、簡単な手順概要です。
Lambdaファンクション実装
前回、前々回の記事で言及したコードに以下の内容を反映します(コードは省略します)。
- 前回までの処理でチャンネルのリストのどこまでを取得済みかを判別する
- 残っているチャンネルのリストから特定数のチャンネルのメッセージを取得する
- まだ未取得のチャンネルが残っていたら、取得済みのチャンネル数を次のLambdaに引き渡す
Step Functions作成
ワークフロー作成
まず最初にワークフローを作成します。
ワークフローはAmazon States Languageと呼ばれる言語で記述します(形式はJSON)。
前述のワークフローを実現するため、以下のようなコードを記述しました。文法の詳細は上記ドキュメント等を参照ください。
{
"Comment": "channels.list",
"StartAt": "channels.list",
"States": {
"channels.list": {
"Type": "Task",
"Resource": "arn:aws:lambda:ap-northeast-1:xxxxxxxx:function:channelslist",
"Next": "isFinished"
},
"isFinished": {
"Type": "Choice",
"Choices": [
{
"Variable": "$.result",
"StringEquals": "-1",
"Next": "finished"
},
{
"Variable": "$.result",
"StringEquals": "1",
"Next": "channels.list"
}
],
"Default": "channels.list"
},
"finished":{
"Type": "Pass",
"End": true
}
}
}
CloudWatch Events設定
CloudWatch Eventsによって定期的にStep Functionsが実行されるように設定します。
動作確認
指定した時刻になればStep Functionsが実行されます。
全て正常に完了すれば以下のように緑色で全てのタスクが完了します。
おわりに
今回は、Step Functionsを使ってSlackの全チャンネルの1日分メッセージの取得を自動化する試みをご紹介しました。
あまりStep Functionsのメリットを享受出来たかはわかりませんが、「使ってみたかった」ってあると思うんです。