JAWS Days 2021 https://jawsdays2021.jaws-ug.jp/timetable/track-c-1500/
Step Functions Expressで作るフルマネージドなサーバーレスバッチ遠藤 大輔
View Slide
はじめに• コメント待ちしております!• jawsdays2021• jawsug• jawsdays2021_C
遠藤 大輔Daisuke Endo株式会社ゆめみ• 2019年, 株式会社ゆめみに入社• 趣味はドラム, コンガ演奏• Twitter: @DddEndow好きなAWSのサービス:Step Functions
よくあるバッチ処理のめんどくささ
外部APIバッチサーバーユーザーデータ取得
外部APIバッチサーバーユーザーデータ取得5〜10分毎処理時間:数分実装も簡単
外部APIバッチサーバーユーザーデータ取得5〜10分毎処理時間:数分実装も簡単l サーバーl ミドルウェアl フレームワークわざわざ用意するのめんどう→サクッと作りたい!
AWS Lambdaなら全部解決する?
AWS Lambda処理が複雑になると…• コードがスパゲッティ化• 責務が大きくなりすぎる• 並列処理が辛い
そこでAWS Step Functions
AWS Step Functions• サーバーレスな関数オーケストレーター• イベント駆動型のワークフローを構築• 並列処理, 例外処理, 再試行ロジックなどを管理可能• Lambdaなど他のサービスと組み合わせ可能
並列処理例外処理条件分岐
でも、あまり現実的なアーキテクチャではなかった• 料金• DBコネクション問題• Lambdaのコールドスタート
それが
料金(2019/12)→Step Functions Express WorkflowsDBコネクション問題(2020/7)→RDS ProxyLambdaのコールドスタート(2019/9)→1分から1秒に改善
AWSがサーバーレスバッチを作れと言っている!!
というわけで
作りました
• 数万ユーザーの処理が30秒で完了ユーザー毎に外部API実行 + DBに書き込み• コストも1万円/月以下(Step Functions, Lambda)
(もう全部サーバーレスバッチでいいんじゃない?)
でも大変なことや辛いこともたくさんあった
でも大変なことや辛いこともたくさんあった今回のメインコンテンツ
アジェンダ• 並列処理• データベース接続• CI/CD• ログ・X-Ray
並列処理
Step Functions
①対象ユーザーを一覧取得②外部APIへリクエスト③データ処理&保存
①対象ユーザーを一覧取得②外部APIへリクエスト③データ処理&保存ユーザー単位で並列処理
Mapステート• Step Functionsの状態の一つ• タスク単位で並列処理が可能• パラメータ一個で同時実行数を制御可能• キューやイベントの管理不要並列処理Mapステート
ユーザー単位で並列処理
なんか二重になってない?
https://docs.aws.amazon.com/ja_jp/step-functions/latest/dg/amazon-states-language-map-state.htmlMapステートの同時実行数• 並列数の上限は無限• 同時実行数は約40が上限• →多重にすることで(たぶん)対策
これで一安心!X-Rayで性能を確認してみよう!
これで一安心!X-Rayで性能を確認してみよう!→LambdaのPendingが大量に…
Lambdaのクォータ• リクエスト数/秒の制限• 同時実行数の10倍• 一万ぐらいまではすぐにあげてくれる• それ以上は実績やデータが必要• GetFunction APIのリクエスト制限• 100リクエスト/秒• コールドスタートの際に実行• デプロイパッケージの取得などに利用
Lambdaのクォータ• Mapの並列数を200ぐらいにしたらスムーズに• 急ぎでないなら40ぐらいでいいかも• Mapを多重にする意味あまりないんじゃ
まるっとうまく動くようになった!
まるっとうまく動くようになった!→ユーザー数増やしたらStep Functionsからエラー出るようになった…
Step Functionsのデータサイズ制限• タスク, ステート, 入出力のデータサイズ• 約260KBの制限• Mapステートの前後で制限オーバー• Map全体で受け渡すデータ量で計算• 300B/ユーザー x 1000人 = 300KB
Step Functionsのデータサイズ制限• S3に一時保存することで回避• 各ユーザーのKey(ID)だけ渡す• S3が強い読み込み整合性をサポート• 上書きPUT, DELETEしても即座に反映• 不要なパラメータはMapの最後に削除ユーザーIDの配列必要なデータのみ渡すユーザーデータ
S3 APIの実行コスト削減と差分対策• Lambda実行のたびにS3から取得すると高コスト• ハンドラー外で取得しかし…
古いデータを参照してしまう問題• 10分間隔であればLambdaの実行基盤がリセットされると予想→実際には稀に実行基盤が残っていて古いデータを参照• ハンドラー外にしたのが裏目に• 実行基盤がリセットされるタイミングは制御できない• S3のオブジェクトのMetadataにバージョン情報を追加してチェックすることで対策
データベース接続
RDS Proxy• DBコネクションのプーリング&共有が可能• Lambdaがコネクションを使い潰す問題を解決• IAM接続とID/Pass接続の二種類
コネクション数の節約• Lambdaハンドラー外でDBコネクションを生成• コネクションが切断した場合にLambdaの実行基盤を終了するエラーハンドリングが必要• RDS Proxy• 数百->数十程度に圧縮可能両方を組み合わせることで数千→数十コネクションまで節約
書き込み処理をまとめる• 1ユーザー毎に書き込み処理を行うのはNG• Kinesisで100人ずつにまとめてバルクアップデート• Step FunctionsやX-Rayで追跡できなくなるのが欠点
CI/CD
CodePipelineGitHubpullsam buildsam packageTemplate fileStackStackStackCloudFormation
Stackを分割するメリット• 複数のグループ毎にリソースを展開できる• パラメータを書き換えるだけ• エンタープライズコネクションなどで効果を発揮• 物理的・論理的にセキュア• ログやメトリクスの管理がしやすい• どのリソースで障害が発生したかがすぐにわかる
テンプレートを使い回すことでこんなことも
Stackを分割するデメリット• リソースが大量に生成される• Step Functions用のLambdaダッシュボードがなかったら心が折れてた
ログ・X-Ray
ログ• Step Functionsの実行ログを収集可能• Step Functions独自のステータスで出力• ちょっとクセがある• エラーの内容にLambdaやStateの情報が含まれない• デバッグが大変• (アップデート待ってます)
X-Ray• Step Functionsに対応(2020/9)• ワークフロー全体を監視可能• 並列処理も時系列で見れる
まとめ
まとめ• 並列処理• データベース接続• CI/CD• ログ・X-Ray
サーバーレスバッチという選択肢• 開発に集中できる• リソースやミドルウェアを気にする必要が(あまり)ない• 高性能• サーバーレスだからこそできる設計• 低コスト• 必要な時に必要なだけ
リソースに縛られないバッチシステム→より効率良く価値を提供
宣伝AWS Summitに登壇しますセッションタイトル「サーバー立てっぱなしはもったいない!サーバーレスのみで構築する中頻度&短時間バッチ」
Thank you for watching!YUMEMI.inc, Daisuke EndoTwitter: @DddEndow