【導入文】
こんにちは。社内システムのクラウド化を支援している「僕」です。
ハードウェアを愛する半導体エンジニアの「妻」にAWSを語るこのシリーズ。今回は、最近アップデートされたばかりのLambdaの新機能と、そこに潜むちょっと怖い「罠」について妻と検証した日の会話をお届けします。
1. 【プロローグ】1MBの荷物を直接投げ込める魔法
僕: 「ねえ聞いて! ついにAWS Lambdaの『非同期呼び出し』で、一度に送れるデータ(ペイロード)の上限が、256KBから1MBに拡張されたんだ!」
妻: 「へえ。外部ストレージ(S3)をわざわざ経由しなくても、1MBのまとまったデータを直接データバスに流し込めるようになったのね。L1キャッシュが増量されたみたいで便利じゃない。」
僕: 「そうそう! これで、ちょっとした画像データや重いJSONファイルなら、直接Lambdaに投げ込めるようになったんだよ!」
妻: 「でもちょっと待って。『非同期(投げっぱなし)』なんでしょ? 工場の天井を走る自動搬送台車(OHT)にウェハーをポンと乗せて『あとはよろしく!』って送り出した後、受け取り側の装置がエラーで止まってたら、そのデータはどうなるの?」
僕: 「えっ? 失敗したら普通にポイッとエラーが返ってきて終わりじゃないの?」
妻: 「本当に? クラウドの『投げっぱなし』ってそんなに潔いのかしら。ちょっと検証してみましょ。」
2. 【Tipsのタネ明かし】非同期呼び出しの「自動再配達」機能
僕: 「……ということで、検証の前に種明かしを。Lambdaには『同期(その場で結果を待つ)』と『非同期(AWS側に処理を預けて結果を待たない)』の2種類の呼び出し方があるんだ。」
妻: 「同期回路と非同期回路みたいなものね。」
僕: 「非同期呼び出しは、イベント駆動でよく使われるんだけど、実はこの裏側には**『処理がエラーになった場合、AWS側が勝手に再実行(リトライ)してくれる』**という強力な仕組みが隠れてるんだ。」
3. 【実践Tips】恐怖の「ゾンビ・リトライ」を発生させる手順
僕: 「では、この親切な機能が『罠』に変わる瞬間を、あえて意図的に引き起こしてみるよ。」
-
絶対失敗するLambdaを作る
Pythonなどで、呼び出されたら必ずraise Exception("わざとエラー")を起こすような、バグ入りのLambda関数を作成する。 -
1MBギリギリのデータを非同期で送りつける
AWS CLIを使って、ダミーのテキストデータ(約1MB)をInvokeコマンドの--invocation-type Event(非同期モード)でこの関数に送信! - ログの観察(罠の発動)
僕: 「ほら、コマンドの実行自体は『受け付けました(Status 202)』って即座に返ってきたよ。」
妻: 「ステータス202って、単に手前のバッファメモリが『データ受け取ったよ』って言ってるだけでしょ? メインのプロセッサが処理したわけじゃないわ。」
僕: 「その通り。で、数分後にCloudWatch Logs(実行記録)を確認すると……うわっ! 自分が1回しか実行していないはずのLambdaが、エラーを吐きながら何度も何度も勝手に再実行されてる!」
4. 【解説と解決策】なぜ勝手に動き続けるのか?
僕: 「なにこれ、ゾンビみたいに何度も蘇ってエラーを吐き続けてるよ!」
妻: 「バッファに受け取った後、どういう挙動になってるの?」
僕: 「AWSのドキュメントをよく読んだら、非同期で受け取ったデータはAWS内部のキュー(待ち行列)に一度入る仕様なんだ。で、処理に失敗すると『あれ? ネットワークのノイズかなんかで、たまたま失敗したのかも』と思って、時間を空けて 最大2回(合計3回)まで自動的に再配達(リトライ) しようとするんだって。」
妻: 「なるほど、通信プロトコルの自動再送要求(ARQ)と同じね。親切な設計だけど、今回みたいなプログラムのバグ(根本的な欠陥)の場合は、何度再送してもエラーになるのは当たり前じゃない。もしこれが『重い処理』を伴う1MBのデータだったら、無駄なリトライのたびにLambdaのクロックサイクル(実行時間=コスト)を食いつぶすことになるわよ。」
僕: 「確かに! 宅配便のお兄さんが、留守の家に何度も重い荷物を運んできてくれるようなものだけど、そもそも住所(プログラム)が間違ってたら無駄なコストになっちゃうね。」
解決策のTips:
このゾンビ化を防ぐには、非同期呼び出しの設定で「最大再試行回数」を0にするか、デッドレターキュー(DLQ)やOn-Failureの送信先(エラー用の通知先) を必ず設定しましょう。
僕: 「DLQっていう設定をしておけば、『再配達に失敗した荷物(エラーになったデータ)』を、いつまでも処理し続けずに、別の場所(SQSやSNSなど)に安全に退避させることができるんだ。」
妻: 「つまり、処理できなかった不良品のデータをいつまでもラインに流し込まずに、別の『リジェクトボックス』に弾き出すってことね。歩留まり管理とエラーハンドリングの基本じゃない。AWSもちゃんと考えてるわね。」
5. 【お片付け】無駄な実行課金に注意
僕: 「非同期の『投げっぱなし』の裏には、AWSの執念深い再配達システムがあったんだね……。」
妻: 「データバスの幅が1MBに広がって便利になった分、エラー時の影響も大きくなるわ。非同期を使うなら、そのDLQ? っていうリジェクトボックスの設定は絶対に鉄則よ。」
僕: 「勉強になった! じゃあ検証も終わったし、ご飯にしようか。」
妻: 「ちょっと待って。さっきの『絶対失敗するLambda』、ちゃんと削除した? 放置してると、もし誰かが間違って非同期で呼び出したら、また無駄にリトライして我が家のOpEx(お小遣い)から課金されるわよ。」
僕: 「おっと危ない! すぐに関数を削除(Delete)してきます!」
【結びの文】
ペイロード枠が1MBに拡大し、S3を経由せず直接データを送り込めるようになってますます便利になったLambdaの非同期呼び出し。しかし、ハードウェアエンジニアの妻が指摘した通り、エラー時の「再配達(リトライ)」の仕様を理解し、正しいエラー退避ルート(DLQ)とお片付けを忘れないように十分ご注意ください!