AWS Dev Day 2022 Japan: https://aws.amazon.com/jp/events/devday/japan/
登壇レポートブログ: https://blog.serverworks.co.jp/aws-dev-day-online-japan-2021-report-hashimoto
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.サーバーレスな社内業務システムを稼働させて1年経ったので、今⽇までの⾜跡を語ろうと思う橋本 拓弥 / HASHIMOTO TakuyaB - 4Corporate Engineer株式会社サーバーワークス / Serverworks Co., Ltd.
View Slide
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.■ 名前橋本 拓弥 / HASHIMOTO TakuyaSpeaker■ 所属株式会社サーバーワークスプロセスエンジニアリング部コーポレートエンジニア■ SNSTwitter: @hassaku_63GitHub: hassaku63
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.■ 普段の仕事開発寄りの社内 SESpeaker• MSP/バックオフィス系• CRM (Salesforce)• AWS Step Functions• Python• Serverless Framework■ SNSTwitter: @hassaku_63GitHub: hassaku63
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.Serverworks ?AWS 特化のインテグレーター• 国内では⽼舗な AWS パートナー企業• 最上位認定 “AWS Premier Tier Service Partner” (2014年〜)公表実績(2022年8⽉時点)• 1050 社• 14200 プロジェクト
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.Serverworks ?https://www.serverworks.co.jp/recruit/We are Hiring(カジュアル⾯談やってます)
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.• ⽉間 1,000 件超(2022年10⽉時点の実績)の請求書作成 & 送付業務をAWS Step Functions + AWS Lambda (+α) で⾃動化した• サーバーレスの開発の実際のところ• AWS Step Functions はいいぞ今⽇お伝えしたいこと
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.• システム概要と開発背景• 請求書⾃動送付システムの実装・設計• 開発・保守で⾏った意思決定やポイント• まとめAgenda
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.システム概要と開発背景
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.請求業務にまつわるデータ管理請求の元データはすべて Salesforce に集約• 取引先、担当者• 商談、商品情報• インテグレーション• 運⽤代⾏ (MSP)• 請求代⾏ (AWS 利⽤料)• 売上(会計)• 請求、請求明細
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.請求業務と関連システム(移⾏前)Salesforce(1) 請求データ作成データ連携SaaS請求書 ExcelアップロードBox請求書 Excel 作成Gmail / 郵送(3) pdf にして送信or 郵送⼿配取引先(2) ダウンロード
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.請求業務と関連システム(移⾏前)Salesforce(1) 請求データ作成データ連携SaaS請求書 ExcelアップロードBox請求書 Excel 作成Gmail / 郵送(3) pdf にして送信or 郵送⼿配取引先(2) ダウンロードn 百件(ほぼ⼿作業)
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.請求業務と関連システム(移⾏前)Salesforce(1) 請求データ作成データ連携SaaS請求書 ExcelアップロードBox請求書 Excel 作成Gmail / 郵送(3) pdf にして送信or 郵送⼿配取引先(2) ダウンロードEoS
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.請求業務と関連システム(移⾏前)Salesforce(1) 請求データ作成データ連携SaaS請求書 ExcelアップロードBox請求書 Excel 作成Gmail / 郵送(3) pdf にして送信or 郵送⼿配取引先(2) ダウンロード・数百件/⽉以上のメール送付(⼿作業)・データ連携 SaaS が EoS・請求書を郵送する業務負担😩
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.請求業務と関連システム(移⾏後)Salesforce(1) 請求データ作成請求書データアップロードBox請求書作成&送付システム取引先AWSAPI GatewayAWSStep FunctionsAWSLambda(PDF, Excel, 利⽤明細)SendGrid⾃動送付 OK の請求ならメール⾃動送付
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.請求業務と関連システム(移⾏後)Salesforce(1) 請求データ作成請求書データアップロードBox請求書作成&送付システム取引先AWSAPI GatewayAWSStep FunctionsAWSLambda(PDF, Excel, 利⽤明細)SendGrid⾃動送付 OK の請求ならメール⾃動送付・メール送付の⾃動化(半数以上)・AWS で内製化・ペーパーレスへの移⾏🎉
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.移⾏による変化Before After• ⼤量の⼿作業送付• 外部 SaaS が EoS• 半数以上の送付を⾃動化• AWS で内製化($10.0/1ヶ⽉ 程度)• ペーパーレス移⾏Keep• 特別対応案件の業務継続(Excel を利⽤)
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.請求書⾃動送付システムの実装
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.技術スタック• Python 3.8• Serverless Framework (2.x)• AWS(⼀部抜粋)• AWS Step Functions• AWS Lambda• 3rd party Services• Salesforce (Salesforce)• Box (Box.com)• SVF Cloud (ウイングアーク1st)• SendGrid (SendGrid)• Datadog (Datadog)
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.構成図
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.構成図Salesforce からのリクエストを受け付けるフロントエンド的役割
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.構成図1件の請求に対する処理を担う部分(請求書作成、AWS利⽤明細作成、送付)
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.構成図Request:- bill_ids: list- auto_send: bool
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.構成図Request:- bill_ids: list- auto_send: bool請求ID 1件ごとに分割し後続のステートマシンを実⾏開始Start× n回
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.構成図Request:- bill_ids: list- auto_send: bool請求ID 1件ごとに分割し後続のステートマシンを実⾏開始請求書 (Excel, PDF)作成+ アップロードStart× n回
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.構成図Request:- bill_ids: list- auto_send: bool請求ID 1件ごとに分割し後続のステートマシンを実⾏開始請求書 (Excel, PDF)作成+ アップロード利⽤明細 (csv) 作成Start× n回
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.構成図Request:- bill_ids: list- auto_send: bool請求ID 1件ごとに分割し後続のステートマシンを実⾏開始Start× n回請求書 (Excel, PDF)作成+ アップロードメール送信利⽤明細 (csv) 作成
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.構成図(ステートマシン)■ 請求書作成1. Salesforce から請求データをクエリ2. 請求書作成 (PDF, Excel)3. アップロード (Box + S3)4. AWS 利⽤料に関する請求であれば後続の「AWS 利⽤明細作成」を開始5. ⾃動送付フラグが有効であれば後続の「メール送付」を開始
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.構成図(ステートマシン)■ AWS 利⽤明細作成1. Salesforce から AWS 利⽤料をクエリ2. 請求に紐づく AWS アカウントの数だけ繰り返す1. 明細 csv 作成2. アップロード (Box + S3)3. ⾃動送付フラグが有効であれば後続の「メール送付」を開始
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.構成図(ステートマシン)■ メール送付1. Salesforce から宛先情報をクエリ2. 送信猶予として⼀定時間待機3. S3 から成果物 (pdf, csv) をダウンロードしメールに添付して送信
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.Topics1. リトライやエラー制御はステートマシンに移譲2. 成果物 (PDF など) の情報をステートマシンあるいはタスク間で直接扱わない3. マネジメントコンソールが使いやすい4. デプロイ5. メール送信の是⾮6. ジョブの成否監視と通知7. ステートマシンの分割設計の是⾮8. テスト
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.Topics1. リトライやエラー制御はステートマシンに移譲2. 成果物 (PDF など) の情報をステートマシンあるいはタスク間で直接扱わない3. マネジメントコンソールが使いやすい4. デプロイ5. メール送信の是⾮6. ジョブの成否監視と通知7. ステートマシンの分割設計の是⾮8. テストStep Functions を利⽤する上での(よくある?)⼯夫の話
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.Topics1. リトライやエラー制御はステートマシンに移譲2. 成果物 (PDF など) の情報を直接扱わない3. マネジメントコンソールが使いやすい4. デプロイ5. メール送信の是⾮6. ジョブの成否監視と通知7. ステートマシンの分割設計の是⾮8. テストStep Functions を利⽤する上での(よくある?)⼯夫の話今回の案件で⾏った設計や実装の意思決定と、それに伴うトレードオフ
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.(1)リトライやエラー制御はステートマシンに移譲実装側ではできるだけ関与しないで任せる⽅針• 業務⽂脈的に意味のある事象をステートマシン上のエラーで表現• 失敗した場所が視覚的にわかりやすい• 例外は基本的にそのまま失敗させる• 「1件の Fail = 請求漏れ」なのでそもそもリカバリ対応は必須• トランザクション区間がないので重症化する場所が少ない• 「とりあえず落とす」が⼀番安全で、かつ⼗分対応可能• リトライは外部サービスの API を呼ぶ場所で利⽤• SVF Cloud, SendGrid, Box• Timeout かスロットリングで失敗するケースが観測上多かった• リトライ間隔は Exponential BackoffCatch による失敗例Step Functions を利⽤する上での(よくある?)⼯夫の話
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.(1)リトライやエラー制御はステートマシンに移譲実装側ではできるだけ関与しないで任せる⽅針• 業務⽂脈的に意味のある事象をステートマシン上のエラーで表現• 失敗した場所が視覚的にわかりやすい• 例外は基本的にそのまま失敗させる• 「1件の Fail = 請求漏れ」なのでそもそもリカバリ対応は必須• トランザクション区間がないので重症化する場所が少ない• 「とりあえず落とす」が⼀番安全で、かつ⼗分対応可能• リトライは外部サービスの API を呼ぶ場所で利⽤• SVF Cloud, SendGrid, Box• Timeout かスロットリングで失敗するケースが観測上多かった• リトライ間隔は Exponential BackoffCatch による失敗例※右図はエラー制御の実例(メール送付ジョブ)Step Functions を利⽤する上での(よくある?)⼯夫の話
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.(1)リトライやエラー制御はステートマシンに移譲Catch による失敗例Step Functions を利⽤する上での(よくある?)⼯夫の話「適切な担当者がいない」を表現する Fail 状態に遷移
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.(1)リトライやエラー制御はステートマシンに移譲Catch による失敗例「適切な担当者がいない」を表現する Fail 状態に遷移送付先としての役割を持つ担当者をクエリしたStep Functions を利⽤する上での(よくある?)⼯夫の話
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.(1)リトライやエラー制御はステートマシンに移譲Catch による失敗例結果が0件だった場合ユーザー定義の例外を送出「適切な担当者がいない」を表現する Fail 状態に遷移送付先としての役割を持つ担当者をクエリしたStep Functions を利⽤する上での(よくある?)⼯夫の話
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.(2) 成果物 (PDF など) の情報を直接扱わない極⼒⼤きなペイロードをタスク間の受け渡しで扱わないこと• ステートマシン上で扱うファイルコンテンツ (PDF, csv) を S3 で扱う• タスク処理中の⼀時ファイルの置き場として利⽤• ベストプラクティスに記述あり「ラージペイロードを渡す代わりに Amazon S3 ARNs を使⽤する」 (※1)• 後から使う際はハンドラの /tmp 以下に都度ダウンロード• AWS サービス同⼠の連携であるため、容易に利⽤でき安全に認証できる• Box は業務担当者向けに最終成果物をアップロードする⽬的でのみ利⽤※1 ... https://docs.aws.amazon.com/ja_jp/step-functions/latest/dg/avoid-exec-failures.htmlStep Functions を利⽤する上での(よくある?)⼯夫の話
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.(3) マネジメントコンソールが使いやすい⾒やすい、わかりやすい(主にリトライ時)• ステータスフィルタと実⾏名による検索• どこで失敗したのか⼀⽬瞭然• 失敗した「実⾏」のリトライが容易Step Functions を利⽤する上での(よくある?)⼯夫の話
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.(3) マネジメントコンソールが使いやすい⾒やすい、わかりやすい(主にリトライ時)• ステータスフィルタと実⾏名による検索• どこで失敗したのか⼀⽬瞭然• 失敗した「実⾏」のリトライが容易ステータスフィルタExecution Name のフィルタ※請求 ID のプレフィックスを命名規則にしているStep Functions を利⽤する上での(よくある?)⼯夫の話
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.(3) マネジメントコンソールが使いやすい⾒やすい、わかりやすい(主にリトライ時)• ステータスフィルタと実⾏名による検索• どこで失敗したのか⼀⽬瞭然• 失敗した「実⾏」のリトライが容易Catch による失敗例(再)ステートの最終遷移先可能で発⽣事象を把握Step Functions を利⽤する上での(よくある?)⼯夫の話
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.(3) マネジメントコンソールが使いやすい失敗した Execution の詳細画⾯で“New execution” をクリックStep Functions を利⽤する上での(よくある?)⼯夫の話
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.(3) マネジメントコンソールが使いやすい失敗した Execution の⼊⼒値がコピーされるランダム ID で Execution Name が⼊⼒済み(任意に変更可能)Step Functions を利⽤する上での(よくある?)⼯夫の話
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.(4) デプロイ現状はローカルマシンからの “serverless deploy” コマンド• 設定ミスの暫定対策として Makefile を使った簡易的なガードレールを作成• 当初はこれで必要⼗分• 最低限の実装でミスの原因を潰せた• デプロイ⾃体も(依存関係まわりで)不安定な時期があり、CI に載せたくなかった• ⾃分以外のアサインが増えたらデプロイタスクは⾃動化しようと思っている• AssumeRole 経由で本番アカウント⽤のプロファイルを保持• >>> AWS_PROFILLE=foo make prod-deploy # npx sls deploy• 管理もデプロイもほぼ⾃分メインなのでギリギリ間に合ってる(?) が、好ましくはない• AWS_PROFILE や環境変数の設定間違いが起きる(起きた)• 個⼈のローカルマシンが本番アカウントの知識を持っている※コードスニペットは Appendix に記載今回の案件で⾏った設計や実装の意思決定と、それに伴うトレードオフ
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.(5) メールによる請求書送付の是⾮• 良い⽅法ではない認識、やめたいとは思っている• 当初、最速で作れる⼿段を模索した結果としてそうなった• ファイル共有プラットフォームの利⽤に切り替えたかったが諸般の事情で断念• バウンス対応が⼀番運⽤シーンで⼿間がかかる今回の案件で⾏った設計や実装の意思決定と、それに伴うトレードオフ
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.(6) ジョブの成否監視と通知前提要件• 「どの顧客のどの請求が失敗したか︖」を特定したい• ステートマシンの Execution ID と⼊⼒値を、通知⽂で知りたい• 失敗したジョブ(=請求1件)は、原則すべて個別確認してリカバリを判断する必要がある• ステートマシンの Fail (正確には、発⾏に失敗した ”請求”)はすべてキャッチしたい• 失敗したジョブは原則的に同⽇内なるはやのリカバリが必要• 遅延は⾃社の回収遅延や、取引先の経理の⼊⾦業務に影響する• 対応漏れは NG だが、再実⾏等のリカバリ対応が重複するのも NG (顧客が混乱するため)今回の案件で⾏った設計や実装の意思決定と、それに伴うトレードオフ
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.(6) ジョブの成否監視と通知実装(最初期)• Datadog Integration を⽤いてステートマシンの Fail を監視していた• 1時間未満で即実装できる点が素晴らしかった• メンテナの⽴場としては監視・通知要件を⼗分満たしていなかった• 失敗したステートマシンの個別の情報がわからない(Execution ARN, Input)• 「直近 N 分間でエラーがあったかどうか」の判定であるため、アラート通知のされ⽅と障害対応の実態(1件単位を⾒たい)がリンクしない• 「要対応のレギュラー事象が発⽣している」ことを知らせる仕組みとしては依然有⽤• 業務担当者(not 技術職)向けの Notice として残している実装(現在)• EventBridge + Amazon SQS + Lambda 経由の通知に変更• ステートマシンの実⾏状態変化 (to Fail) を拾ってキューイング、Lambda から Slack の専⽤チャンネルに通知• 「Slack の通知1件 = 1件の請求がストップ」であるため解釈しやすいのが好都合だった• 「通知に対して⾃分がリアクションしていない=対応漏れ」であるとわかるので漏れが起きづらい今回の案件で⾏った設計や実装の意思決定と、それに伴うトレードオフ
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.(6) ジョブの成否監視と通知実装(最初期)• Datadog Integration を⽤いてステートマシンの Fail を監視していた• 1時間未満で実装できる点が素晴らしかった• メンテナの⽴場としては監視・通知要件を⼗分満たしていなかった• 失敗したステートマシンの個別の情報がわからない(Execution ARN, Input)• 「直近 N 分間でエラーがあったかどうか」の判定であるため、アラート通知のされ⽅と障害対応の実態(1件単位を⾒たい)がリンクしない• 「要対応のレギュラー事象が発⽣している」ことだけを知らせる仕組みとしては依然有⽤• 業務担当者(not 技術職)向けの Notice として残している実装(現在)• EventBridge + Amazon SQS + Lambda 経由の通知に変更• ステートマシンの実⾏状態変化 (to Fail) を拾ってキューイング、Lambda から Slack の専⽤チャンネルに通知• 「Slack の通知1件 = 1件の請求がストップ」であるため解釈しやすいのが好都合だった• 「通知に対して⾃分がリアクションしていない=対応漏れ」であるとわかるので漏れが起きづらいDatadog IntegrationStep FunctionsState machineDatadog直近の N 分間で “Fail” が1件以上ならアラート︕今回の案件で⾏った設計や実装の意思決定と、それに伴うトレードオフ
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.(6) ジョブの成否監視と通知実装(最初期)• Datadog Integration を⽤いてステートマシンの Fail を監視していた• 1時間未満で実装できる点が素晴らしかった• メンテナの⽴場としては監視・通知要件を⼗分満たしていなかった• 失敗したステートマシンの個別の情報がわからない(Execution ARN, Input)• 「直近 N 分間でエラーがあったかどうか」の判定であるため、アラート通知のされ⽅と障害対応の実態(1件単位を⾒たい)がリンクしない• 「要対応のレギュラー事象が発⽣している」ことだけを知らせる仕組みとしては依然有⽤• 業務担当者(not 技術職)向けの Notice として残している実装(現在)• EventBridge + Amazon SQS + Lambda 経由の通知に変更• ステートマシンの実⾏状態変化 (to Fail) を拾ってキューイング、Lambda から Slack の専⽤チャンネルに通知• 「Slack の通知1件 = 1件の請求がストップ」であるため解釈しやすいのが好都合だった• 「通知に対して⾃分がリアクションしていない=対応漏れ」であるとわかるので漏れが起きづらいDatadog IntegrationStep FunctionsState machineDatadog・アラートの情報量が「N 分間で発⽣した Fail 数」になる・Fail Execution の件数しか得られない・個別の Fail Execution に関する情報は取れない・アラート通知と、実際に⾒るべき Execution 件数が⼀致しない・N 分間の中で複数件 Fail することがありえる直近の N 分間で “Fail” が1件以上ならアラート︕今回の案件で⾏った設計や実装の意思決定と、それに伴うトレードオフ
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.(6) ジョブの成否監視と通知実装(最初期)• Datadog Integration を⽤いてステートマシンの Fail を監視していた• 1時間未満で実装できる点が素晴らしかった• メンテナの⽴場としては監視・通知要件を⼗分満たしていなかった• 失敗したステートマシンの個別の情報がわからない(Execution ARN, Input)• 「直近 N 分間でエラーがあったかどうか」の判定であるため、アラート通知のされ⽅と障害対応の実態(1件単位を⾒たい)がリンクしない• 「要対応のレギュラー事象が発⽣している」ことだけを知らせる仕組みとしては依然有⽤• 業務担当者(not 技術職)向けの Notice として残している実装(現在)• EventBridge + Amazon SQS + Lambda 経由の通知に変更• ステートマシンの実⾏状態変化 (to Fail) を拾ってキューイング、Lambda から Slack の専⽤チャンネルに通知• 「Slack の通知1件 = 1件の請求がストップ」であるため解釈しやすいのが好都合だった• 「通知に対して⾃分がリアクションしていない=対応漏れ」であるとわかるので漏れが起きづらいEvent BridgeStep FunctionsState machineSlackFail に遷移した Execution を通知Event BridgeExecution FailEvent RuleSQSQueueLambdaFunction・Fail した Execution ごとの情報が Consumer 側で取得できる→ アラート通知⽂をより Actionable にできる・Slack への通知件数と、実際に⾒るべき Execution 件数が⼀致する→ 対応漏れしづらくなる今回の案件で⾏った設計や実装の意思決定と、それに伴うトレードオフ
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.(6) ジョブの成否監視と通知実装(最初期)• Datadog Integration を⽤いてステートマシンの Fail を監視していた• 1時間未満で実装できる点が素晴らしかった• メンテナの⽴場としては監視・通知要件を⼗分満たしていなかった• 失敗したステートマシンの個別の情報がわからない(Execution ARN, Input)• 「直近 N 分間でエラーがあったかどうか」の判定であるため、アラート通知のされ⽅と障害対応の実態(1件単位を⾒たい)がリンクしない• 「要対応のレギュラー事象が発⽣している」ことだけを知らせる仕組みとしては依然有⽤• 業務担当者(not 技術職)向けの Notice として残している実装(現在)• EventBridge + Amazon SQS + Lambda 経由の通知に変更• ステートマシンの実⾏状態変化 (to Fail) を拾ってキューイング、Lambda から Slack の専⽤チャンネルに通知• 「Slack の通知1件 = 1件の請求がストップ」であるため解釈しやすいのが好都合だった• 「通知に対して⾃分がリアクションしていない=対応漏れ」であるとわかるので漏れが起きづらいEvent BridgeStep FunctionsState machineSlackFail に遷移した Execution を通知Event BridgeExecution FailEvent RuleSQSQueueLambdaFunction・Fail した Execution ごとの情報が Consumer 側で取得できる→ アラート通知⽂をより Actionable にできる・Slack への通知件数と、実際に⾒るべき Execution 件数が⼀致する→ 対応漏れしづらくなる今回の案件で⾏った設計や実装の意思決定と、それに伴うトレードオフ実際の Slack 通知
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.(6) ジョブの成否監視と通知実装(最初期)• Datadog Integration を⽤いてステートマシンの Fail を監視していた• 1時間未満で実装できる点が素晴らしかった• メンテナの⽴場としては監視・通知要件を⼗分満たしていなかった• 失敗したステートマシンの個別の情報がわからない(Execution ARN, Input)• 「直近 N 分間でエラーがあったかどうか」の判定であるため、アラート通知のされ⽅と障害対応の実態(1件単位を⾒たい)がリンクしない• 「要対応のレギュラー事象が発⽣している」ことだけを知らせる仕組みとしては依然有⽤• 業務担当者(not 技術職)向けの Notice として残している実装(現在)• EventBridge + Amazon SQS + Lambda 経由の通知に変更• ステートマシンの実⾏状態変化 (to Fail) を拾ってキューイング、Lambda から Slack の専⽤チャンネルに通知• 「Slack の通知1件 = 1件の請求がストップ」であるため解釈しやすいのが好都合だった• 「通知に対して⾃分がリアクションしていない=対応漏れ」であるとわかるので漏れが起きづらいEvent BridgeStep FunctionsState machineSlackFail に遷移した Execution を通知Event BridgeExecution FailEvent RuleSQSQueueLambdaFunction・Fail した Execution ごとの情報が Consumer 側で取得できる→ アラート通知⽂をより Actionable にできる・Slack への通知件数と、実際に⾒るべき Execution 件数が⼀致する→ 対応漏れしづらくなる今回の案件で⾏った設計や実装の意思決定と、それに伴うトレードオフエラー情報の通知・どのジョブか・どの請求 ID か
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.(6) ジョブの成否監視と通知実装(最初期)• Datadog Integration を⽤いてステートマシンの Fail を監視していた• 1時間未満で実装できる点が素晴らしかった• メンテナの⽴場としては監視・通知要件を⼗分満たしていなかった• 失敗したステートマシンの個別の情報がわからない(Execution ARN, Input)• 「直近 N 分間でエラーがあったかどうか」の判定であるため、アラート通知のされ⽅と障害対応の実態(1件単位を⾒たい)がリンクしない• 「要対応のレギュラー事象が発⽣している」ことだけを知らせる仕組みとしては依然有⽤• 業務担当者(not 技術職)向けの Notice として残している実装(現在)• EventBridge + Amazon SQS + Lambda 経由の通知に変更• ステートマシンの実⾏状態変化 (to Fail) を拾ってキューイング、Lambda から Slack の専⽤チャンネルに通知• 「Slack の通知1件 = 1件の請求がストップ」であるため解釈しやすいのが好都合だった• 「通知に対して⾃分がリアクションしていない=対応漏れ」であるとわかるので漏れが起きづらいEvent BridgeStep FunctionsState machineSlackFail に遷移した Execution を通知Event BridgeExecution FailEvent RuleSQSQueueLambdaFunction・Fail した Execution ごとの情報が Consumer 側で取得できる→ アラート通知⽂をより Actionable にできる・Slack への通知件数と、実際に⾒るべき Execution 件数が⼀致する→ 対応漏れしづらくなる今回の案件で⾏った設計や実装の意思決定と、それに伴うトレードオフ対応漏れなし︕
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.(7) ステートマシンの分割思想の是⾮• ステートマシンの「構成単位」の分割• 請求書作成• AWS 利⽤明細作成• メール送付• ステートマシンの「実⾏粒度」の分割• 請求1件ずつ実⾏ (Execution) する仕様今回の案件で⾏った設計や実装の意思決定と、それに伴うトレードオフ
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.(7-1) ステートマシンの構成単位での分割• 外部サービス API の応答不良による失敗に多少の耐性がつく• 複数の SaaS を使っており、そのうち⼀部サービスは稀に Timeout で失敗することがある• 失敗した場所からリトライすれば良い• 監視・通知の実装が簡単• 何がどう失敗したのかの情報が取りやすい• アラート通知の実装が楽• 外部サービス API の呼び出し頻度をコントロールしづらくなった• 特に Salesforce ではすべてのステートマシンでそれぞれクエリする⽤事がある• サービス(ステートマシン)跨ぎで特定サービスのスロットリングを気にする必要がある構成要素が把握しやすく、基本的には良い判断だった今回の案件で⾏った設計や実装の意思決定と、それに伴うトレードオフ
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.(7-2) ステートマシンの実⾏粒度の分割• ジョブ失敗時の対応が⾮常に楽• 影響範囲の特定• 並列実⾏している ”隣” の請求に影響が出ない• 原因の切り分け調査• 少数であればリトライはコンソールで⼀瞬• 監視・通知の実装が簡単• 何がどう失敗したのかわかる• 外部 API の呼び出しの時間密度が⾼い• Salesforce へのクエリで N+1 ライクな箇所がある• スロットリングを起こしやすい• 分割を進めた弊害で、全体としての API コールの頻度を⾮常にコントロールしづらい直感的で把握しやすい、ただしバッチ処理のアーキテクチャとしては⾮効率メリット デメリット今回の案件で⾏った設計や実装の意思決定と、それに伴うトレードオフ
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.(7-3) 外部サービス API のスロットリング対策[A] そもそも⼤量にコールしないで済むような構成を採る• アーキテクチャを変える、N+1 クエリを回避する、Bulk API があれば⽤いる、など• 正攻法ではあるが限度もある• e.g) サービス側の API 仕様でリクエスト/レスポンスのペイロード⻑上限がある[B] 実⾏間隔を空けて個々でリトライ• タスクの Exponential Backoff リトライや、Execution 1件ごとの実⾏インターバルの指定• 最も簡易的な緩和策• 429 レスポンス時に Retry-After ヘッダを返す API であれば(※1)もう少し建設的な対策ができるかも• ステートマシンの Wait ステート + InputPath で動的な時間指定 + ⾃前のループ構造を実装することで対策になりそう• 採⽤できるかどうかはサービスの API 仕様や、採⽤している SDK / ラッパーライブラリの実装に依る個々のステートマシン、Lambda から直接呼び出す限りは回避が難しい今回の案件で⾏った設計や実装の意思決定と、それに伴うトレードオフ※1 ... 参考: MDN Web Docs - 429 Too Many Requests https://developer.mozilla.org/ja/docs/Web/HTTP/Status/429
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.(7-3) 外部サービス API のスロットリング対策[C] API 呼び出しを直接実⾏せず、レート制御の責務ごと別の Proxy サービスに切り出す• .waitForTaskToken を⽤いて外部 API 呼び出し(およびレート制御)の責務をステートマシンの外部に切り出す• (参考) サービス統合パターン https://docs.aws.amazon.com/ja_jp/step-functions/latest/dg/connect-to-resource.html#connect-wait-token• e.g) SQS を介してステートマシンと外部サービスを同期的に統合する• 同種のクエリ (where 句の条件のみが異なる)をマージできる可能性がある• 構成要素は増えるので、やりたいことに対して Too much の感もある• 素直に元の構成をチャンク対応する⽅向で考えた⽅が建設的では。。。(今回の事例の場合)個々のステートマシン、Lambda から直接呼び出す限りは回避が難しい今回の案件で⾏った設計や実装の意思決定と、それに伴うトレードオフ外部サービスのスロットリング対策は発表者⾃⾝まだ⾒解がふわふわしています。SNS コメント等でご意⾒・フィードバック等あればお聞かせください。ディスカッションしましょう🙏 🙏
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.(8) テスト⼿探り中⾃動化したユニットテスト+ ⼿作業の結合テストでリリース判定している• ユニットテストをかなり⼿厚めにした• Small サイズ (※1) に収まる & ロジック部分のテストを⾃動テストで担保しにいく意識• ⼿元 + GitHub Actions で Lint + Test + Coverage を随時実⾏• 結合テストの領域を(⾃動テストの枠組みで)担保しに⾏くのは諦めた• 結合テストはステートマシン単位、⼿作業で検証• AWS 以外の外部サービスに複数依存している• サービスによっては本番同等の環境再現が困難で⾃動化を諦めた※1 Google Testing Blog - Test Sizes ... https://testing.googleblog.com/2010/12/test-sizes.html今回の案件で⾏った設計や実装の意思決定と、それに伴うトレードオフ
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.(8) テスト• ステートマシン単位の⾃動テストを実現させたい(できてない)• 外部サービス (SaaS) との付き合い⽅が最⼤の課題• Step Functions, Lambda は実際にデプロイする前提で、SaaS 連携の部分をよしなにしたい• localstack, step functions local などのコンテナベース環境はテスト時に利⽤していない• テストのため「だけ」の技術スタック(キャッチアップ & 維持コスト)を要求する• 実環境で動かす場合と、コンテナ環境を動かす場合のメリット差分はなにか︖• そこに⼿間暇かけるよりはデプロイして確認した⽅がより正確で、得るものも⼤きいと考えている• ローカルでのイテレーションが捗る点は利点• ステートの遷移を再現する⽤途としてはありがたい(ただ、環境構築の部分に障壁がある印象)• チームの体制・状況等で結論が変わる可能性はある今回の案件で⾏った設計や実装の意思決定と、それに伴うトレードオフ
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.振り返り
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.振り返りうまくいった 苦労した(している)• 業務的な⽬的は⼗分達成した• AWS での内製化• AWS 利⽤料が約 $10.0/⽉ 前後• ⽚⼿間リソースでなんとか(?)なっている• 時期が偏る稼働特性に噛み合っている• ステートマシンを請求1件単位にしたこと• 失敗状況が追いやすくリトライが容易• 悪い点もあるが、業務の回しやすさはある• 監視• 現状の業務要件に照らして必要⼗分• プロジェクトの計画と下準備• CRM 上の既存データ構造、業務ルールの理解• 移⾏の段取り• システム化 しない スコープの決定• ステートマシン単位のテスト• 外部サービス (SaaS) との付き合い⽅• テスト• スロットリング対策• メンテの頻度が確保できていない• 依存関係のこまめな更新• CI/CD の整備• メールのバウンス対応• 愚直にやるしかない
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.おわりにまだ喋りたいことが ...• トレーシングの活⽤と、ハマった事例• 保守しやすいデータ構造 (Task input/output) の設計• Lambda のデプロイは Zip? コンテナ?• 「AWS SDK サービス統合」は使う︖• たられば話• 懐事情的な制約を外したら採⽤スタックの結論は変わる︖• Python ?• ECS Fargate ?• Serverless Framework? terraform? AWS CDK?
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.おわりにStep Functions はいいぞ
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.Thank you!© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.HASHIMOTO TakuyaServerworks Co., Ltd.Twitter: @hassaku_63We are Hiring !https://www.serverworks.co.jp/recruit
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.Appexdix
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.a. デプロイ⽤ Makefile
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.MakefileMakefile (抜粋)AWS_PROFILE の指定有無をチェックし、プロンプトを出す Python スクリプト“check_profile.py”を実⾏
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.MakefileMakefile (抜粋)prod へのデプロイタスクを “check-aws-profile” に依存することでデプロイ前にプロファイル指定を確認するプロンプトを出すデプロイステージを prefix にしておくことで、tab 補完 -> ⼿拍⼦デプロイ実⾏ ...のような事故が起きづらい
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.ガードレール⽤の簡易補助ツールcheck_profile.py
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.ガードレール⽤の簡易補助ツールcheck_profile.py実際の deploy コマンドを実⾏する前にプロンプトを表⽰して警告
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.Point慣れによる「油断」が発⽣する前提で、その抵抗措置を講じる意識だった• タスクの名前は ”-” でデプロイステージ名を prefix• 最初に “prod” とタイプするので、⼊⼒を「対象環境の認識」から始められる• ⼿拍⼦で tab 補完 → Enter パーン → 「あっっ」する確率が減る(体感)• 本番環境対象の場合のみ AWS_PROFILE の確認⽤プロンプトを出す• 簡易的な CI/CD の承認フローのような感じ• 本番環境の場合のみプロンプトを出すことで「本番」であることを認識しやすくなる• システム側の管理者が複数⼈体制になるならデプロイ⾃動化する• よくあるマージトリガー⽅式の⾃動実⾏にするかどうかは思案中。個⼈的には(今回の案件では)不要と判断• 任意のタイミングで任意の commit, tag をデプロイできる⽅が好み(トリガーは GitHub の UI や⾃作 bot)• ⾃動化をマージトリガーに結合しても、さほど楽にならない(今回の開発規模が⼤きくないことも理由)• 期待する恩恵はデプロイの再現性を⾼めることであって、⾃動実⾏ではない• トラブル時の調査やリカバリで余計な追加要素を考えなくて済む