【レポート】Let’s dive deep into AWS Lambda error handling #AWSSummit

結論:動画見ましょう
2020.09.08

2020年9月8日から30日まで開催されるAWS Summit Onlineのセッションレポートです。本エントリではライブセッションLet’s dive deep into AWS Lambda error handlingをレポートします。

非常に簡潔でわかりやすいセッションでした。かつ大事な話が詰まっていたので、Lambdaをご利用の方、もしくはこれからご利用の予定がある方は、すでに公開された録画を聴講されたほうが良いと思います!たった30分の動画なのでぜひ。 リンクは以下です。

というわけで動画を見ていただきたいのですが、レポートもやります。詳細は動画を見ていただければよいのでダイジェストでやります。

セッション概要

AWS Lambda は 20 以上の AWS サービスをイベントソースとしてサポートし、サーバーレスでイベントドリブンなアプリケーションを開発できるプラットフォームです。AWS Lambda は継続的な運用性の改善が行われ続けておりエラーハンドリングのあり方も大きく変わっています。当セッションでは AWS Lambda を利用したアプリケーションをより適切な設計・実装するために「エラーハンドリング」の観点で Deep Dive し解説します。

スピーカー

レポート

セッション概要

このセッションでは、エラーが発生した際のシステムの動きがどうなるのか、そしてそれをどうLambdaあるいはその周辺のサービスでハンドリングするのかという点を学んでいただきます。Lambdaの基礎やエラーハンドリング以外の点については扱いません。

Everything fails all the time

まずはこのEverything fails all the timeという考えについて知っていただきたいです。Amazon.comのCTOであるWerner Vogelsが提唱した考えなのですが、システムは壊れる前提で設計しましょう、ということです。この考えをあなたのアプリケーションにも適用してください。

当セッションにおけるエラーとは

まずは当セッションで扱うエラーについて定義しておきます。 以下の4点であると定義します。

ではこれらのエラーが起きたとき、システムはどのように振る舞うでしょうか?言い換えるとシステムにはどのような問題が発生するでしょうか?3点挙げます。

1. 不要なリトライ

まず、システムはリトライを繰り返す可能性があります。これにより以下のような問題が発生しえます。

  • 処理時間が長期化する
  • 同時実行数エラーになる
  • AWS利用料が跳ね上がる
  • エラーログが肥大化
  • アラート発報が続く

2. エラーの伝播

特定の処理のエラーが原因で、他の箇所でもエラーが発生してしまうかもしれません。

3. データ整合性が崩れる

例えば

  1. DynamoDBテーブルの更新
  2. Auroraテーブルの更新

という一連の処理があったとします。2. Auroraテーブルの更新の途中でエラーが発生したら、Aurora単体ではロールバックが走ってデータが元の状態になりますが、DynamoDB側は更新済みなので、2者間でデータ不整合が発生してしまいます。

このような問題が発生しえます。そしてEverything fails all the timeと申し上げたとおり、こういった問題が発生する前提にたって対策を講じましょう。

不要なリトライの回避

対策1: 適切なリトライ回数の設定

Lambdaはイベントソースごとにリトライ回数の設定方法が異なります。適切なリトライ回数を設定しましょう。

対策2: 処理失敗時のイベントデータの退避

処理失敗時はそのことを他のサービスに伝えて適切に処理しましょう。イベントソースごとに様々な失敗時のイベント送信先があります。

※筆者コメント 非同期呼び出しのDestinationsとDLQの比較についてはこちら

エラーの伝播の回避

疎結合化

  • Lambdaを同期呼び出しから非同期呼び出しに変える
  • 間にSQS、Kinesis Data Streams、SNSなどのコンポーネントを挟む

非同期呼び出し時のDestinationsを活用する

Lambdaの処理成功時、失敗時にそれぞれ別のサービスをトリガすることができます。イベントドリブンな処理が簡単に構築できます。

緊急停止機構を導入する

以下のような機構を導入します。

  1. Lambda関数のエラーをCloudWatchでモニタリング
  2. しきい値を超えたらSNS→別のLambda関数をトリガ
  3. そのトリガ内で対象のLambda関数の同時実行数を0にする

→Lambda関数が実行されなくなります。

※緊急停止後の回復方法についても要考慮

データ整合性の確保

重複実行を前提とした設計にする→冪等性

  • エラー時に同じデータに対して複数回処理実行される場合がある
  • 「少なくとも1回実行(つまり2回以上実行される場合がある)」というAWSサービスが色々あるので、そもそもエラーハンドリングを考慮しなかったとしても重要な観点

反対処理による処理の取り消し

前述の

  1. DynamoDBテーブルの更新
  2. Auroraテーブルの更新

といったような複数リソースに対する一連の処理がある場合、失敗が発生した箇所から一つずつ遡って処理取り消しを行っていく実装をします。

しかし、正常系の処理に加えて失敗時の処理を実装し、かつその流れを管理するのは大変です。そういった場合はStep Functionsに任せましょう。 各処理はシンプルにして、ワークフローをStep Functionsステートマシンで処理します。

処理する必要のないイベントはスキップする

イベントの有効期限を適切に設定しましょう。