

# AWS Lambda とは
<a name="welcome"></a>

**ヒント**  
ベストプラクティスを使用して Serverless アプリケーションを構築する方法を知るには、Serverless の専門家による無料のハンズオンワークショップに参加します。[こちらをクリックして](https://aws-experience.com/amer/smb/events/series/Get-Hands-On-With-Serverless?trk=188abe3e-9f94-4e84-aefb-398d944ad567%26sc_channel%3Del)サインアップします。

AWS Lambda は、サーバーの管理を行うことなくコードを実行できるコンピューティングサービスです。コードが実行され、スケールアップとスケールダウンが自動的に実行され、従量課金制の価格設定が適用されます。開始するには、「[最初の関数を作成する](getting-started.md)」を参照してください。

Lambda は、次の目的で使用できます。
+ **ファイル処理**: Amazon Simple Storage Service にアップロードされると、ファイルを自動的に処理します。詳細については、「[ファイル処理の例](example-apps.md#examples-apps-file)」を参照してください。
+ **長時間のワークフロー:** [耐久性のある Lambda 関数](durable-functions.md)を使用し、最大 1 年間実行できるステートフルで複数ステップのワークフローを構築します。注文処理、承認ワークフロー、ヒューマンインザループのプロセス、進行状況を記憶する必要がある複雑なデータパイプラインに最適です。
+ **データベースオペレーションと統合の例**: データベースの変更に対応し、データワークフローを自動化します。詳細については、「[データベースの例](example-apps.md#examples-apps-database)」を参照してください。
+ **スケジュールされたタスクと定期的なタスク**: EventBridge を使用して自動オペレーションを定期的に実行します。詳細については、「[スケジュールされたタスクの例](example-apps.md#examples-apps-scheduled)」を参照してください。
+ **ストリーム処理**: 分析とモニタリングのためにリアルタイムのデータストリームを処理します。詳細については、「[Kinesis Data Streams](with-kinesis.md)」を参照してください。
+ **ウェブアプリケーション**: 需要に合わせて自動的に調整するスケーラブルなウェブアプリケーションを構築します。
+ **モバイルバックエンド**: モバイルアプリケーションとウェブアプリケーション用の安全な API バックエンドを作成します。
+ **IoT バックエンド**: ウェブ、モバイル、IoT、およびサードパーティーの API リクエストを処理します。詳細については、「[IoT](services-iot.md)」をご覧ください。

料金に関する情報については、[[AWS Lambda の料金](https://aws.amazon.com/lambda/pricing/)]を参照してください。

## Lambda の仕組み
<a name="how-lambda-works"></a>

Lambda を使用する際、ユーザーが責任を負うのはコードのみです。Lambda は、高可用性コンピューティングインフラストラクチャ上でコードを実行し、サーバーとオペレーティングシステムのメンテナンス、容量のプロビジョニングと自動スケーリング、コードのモニタリング、ログ記録などのすべてのコンピューティングリソースを管理します。

Lambda はサーバーレスのイベント駆動型コンピューティングサービスであるため、従来のウェブアプリケーションとは異なるプログラミングパラダイムを使用します。次のモデルは、Lambda の基本的な仕組みを示しています。

1. [Lambda 関数](concepts-basics.md#gettingstarted-concepts-function)は、Lambda アプリケーションを作成するために使用する基本的な構成要素であり、コードの作成と整理に使用されます。

1. セキュリティとアクセスは、[Lambda のアクセス許可](lambda-permissions.md)を通じて制御し、[実行ロール](lambda-intro-execution-role.md)を使用して、関数が対話できる AWS サービスと、コードと対話できるリソースポリシーを管理します。

1. イベントソースとAWS サービスは Lambda 関数を[トリガー](concepts-event-driven-architectures.md)し、関数が処理するイベントデータを JSON 形式で渡します (これにはイベントソースマッピングが含まれます）。

1. Lambda は、ランタイム、レイヤー、拡張機能をパッケージ化した実行環境で、言語固有のランタイム (Node.js や Python など) を使用して[コードを実行します](concepts-how-lambda-runs-code.md)。

**ヒント**  
**サーバーレスソリューション**を構築する方法については、「[サーバーレスデベロッパーガイド](https://docs.aws.amazon.com/serverless/latest/devguide/)」を参照してください。

## 主な特徴
<a name="features"></a>

**安全なアプリケーションを設定、制御、デプロイします。**
+ [環境変数](configuration-envvars.md)は、新しいコードをデプロイなしでアプリケーションの動作を変更します。
+ [バージョン](configuration-versions.md)は、安定した本番環境を維持しながら、新機能を安全にテストします。
+ [Lambda レイヤー](chapter-layers.md)は、複数の関数間で共通コンポーネントを共有することで、コードの再利用とメンテナンスを最適化します。
+ [コード署名](configuration-codesigning.md)は、承認されたコードのみが本番稼働システムに到達するようにすることで、セキュリティコンプライアンスを強化します。

**確実にスケールしてパフォーマンスを実現。**
+ [同時実行数とスケーリングの制御](lambda-concurrency.md)により、トラフィックの急増時にアプリケーションの応答性とリソース使用率を正確に管理します。
+ [Lambda SnapStart](snapstart.md) はコールドスタート時間を大幅に短縮します。Lambda SnapStart は通常、関数コードを変更することなく、わずか 1 秒未満の起動パフォーマンスを提供できます。
+ [レスポンスストリーミング](configuration-response-streaming.md)は、リアルタイム処理のために大きなペイロードを段階的に配信することで、関数のパフォーマンスを最適化します。
+ [コンテナイメージ](images-create.md)は、コンテナワークフローを使用して、複雑な依存関係を持つ関数をパッケージ化します。

**シームレスに接続して統合します。**
+ [VPC ネットワーク](configuration-vpc.md)は、機密リソースと内部サービスを保護します。
+ 永続データを共有し、関数呼び出し全体でステートフル操作を管理する[ファイルシステム](configuration-filesystem.md)。
+ [関数 URL](urls-configuration.md)は、追加のサービスなしで、パブリック向けの API とエンドポイントを作成します。
+ [Lambda 拡張機能](lambda-extensions.md)は、モニタリング、セキュリティ、運用ツールで関数を強化します。

## 関連情報
<a name="w2aab7c17"></a>
+ Lambda の仕組みについては、「[Lambda の仕組み](concepts-basics.md)」を参照してください。
+ Lambda の使用を開始するには、「[最初の Lambda 関数を作成する](getting-started.md)」を参照してください。
+ アプリケーション例の一覧については、「[サンプルアプリケーションとパターンの使用開始](example-apps.md)」を参照してください。

# Lambda の仕組み
<a name="concepts-basics"></a>

Lambda 関数は、Lambda アプリケーションの構築に使用する基本的な構成要素です。関数を記述するには、Lambda プログラミングモデルを構成する主要な概念とコンポーネントを理解することが不可欠です。このセクションでは、Lambda を使用してサーバーレスアプリケーションの構築を開始するために必要な基本的な要素について説明します。
+ **[Lambda 関数と関数ハンドラー](#gettingstarted-concepts-function)** – Lambda 関数は、イベントに応答して実行されるコードの小さなブロックです。関数は標準 (最大 15 分) または[耐久性](durable-functions.md) (最大 1 年) の場合があります。関数は、アプリケーションの構築に使用する基本的な構成要素です。関数ハンドラーは、Lambda 関数コードが処理するイベントオブジェクトのエントリポイントです。
+ **[Lambda 実行環境とランタイム](#gettingstarted-concepts-runtime)** - Lambda 実行環境は、関数の実行に必要なリソースを管理します。[耐久性のある関数](durable-functions.md)の場合、実行環境には自動状態管理およびチェックポイント機能が含まれます。ランタイムは、関数が実行される言語固有の環境です。
+ **[イベントとトリガー](#gettingstarted-concepts-event)** – 特定のイベントに対応して他の AWS のサービス が関数を呼び出すことができます。耐久性のある関数の場合、イベントは一時停止したワークフローの再開をトリガーすることもできます。
+ **[Lambda のアクセス許可とロール](#gettingstarted-concepts-permissions)** - 関数にアクセスできるユーザーと、関数が操作できる他の AWS のサービス を制御します。耐久性のある関数には、状態管理と拡張実行のための追加のアクセス許可が必要です。

**ヒント**  
サーバーレス開発をより一般的に理解することから開始する場合、「*AWS サーバーレスデベロッパーガイド*」の「[従来の開発とサーバーレス開発の違いの概要](https://docs.aws.amazon.com/serverless/latest/devguide/serverless-shift-mindset.html)」を参照してください。

## Lambda 関数と関数ハンドラー
<a name="gettingstarted-concepts-function"></a>

Lambda では、**関数**はアプリケーションの作成に使用する基本的な構成要素です。Lambda 関数は、ユーザーがウェブサイトのボタンをクリックしたり、Amazon Simple Storage Service (Amazon S3) バケットにファイルがアップロードされたりなど、イベントに応答して実行されるコードです。耐久性のある関数を使用すると、コードはステップ間で実行を一時停止できて、状態が自動的に維持されるため、注文処理やコンテンツモデレーションなどの長時間のワークフローに最適です。関数は、次のプロパティを持つ自己完結型プログラムの一種として考えることができます。

Lambda **関数ハンドラー**は、イベントを処理する関数コード内のメソッドです。イベントに応答して関数が実行されると、Lambda は関数ハンドラーを実行します。関数の実行の原因となったイベントに関するデータは、ハンドラーに直接渡されます。Lambda 関数のコードには複数のメソッドまたは関数を含めることができますが、Lambda 関数には 1 つのハンドラーしか含めることができません。

Lambda 関数を作成するには、関数コードおよびその依存関係をデプロイパッケージにバンドルします。Lambda は、[.zip ファイルアーカイブ](configuration-function-zip.md)と[コンテナイメージ](images-create.md)の 2 種類のデプロイパッケージをサポートします。
+ 関数には特定のジョブまたは目的が 1 つある
+ 特定のイベントに応答して必要な場合にのみ実行される
+ 完了すると自動的に実行が停止される

## Lambda 実行環境とランタイム
<a name="gettingstarted-concepts-runtime"></a>

Lambda 関数は、安全で隔離された*[実行環境](lambda-runtime-environment.md)*内で実行されます。Lambda により、ユーザーに代わってこれが管理されます。[耐久性のある関数](durable-functions.md)の場合、実行環境には状態管理およびワークフロー調整用に追加コンポーネントが含まれています。この実行環境では、関数の実行に必要なプロセスおよびリソースが管理されます。関数が最初に呼び出されると、Lambda は関数を実行するために新しい実行環境を作成します。関数の実行が完了すると、Lambda は実行環境をすぐに停止しません。関数が再度呼び出された場合、Lambda は既存の実行環境を再利用できます。

Lambda 実行環境には、*ランタイム*も含まれています。このランタイムは、Lambda と関数の間でイベント情報やレスポンスを中継する言語固有の環境です。Lambda は、最も人気のあるプログラミング言語向けに多数の[マネージドランタイム](lambda-runtimes.md#runtimes-supported)を提供します。または、ユーザー独自のランタイムを作成することもできます。

マネージドランタイムの場合、Lambda はランタイムを使用する関数にセキュリティ更新プログラムおよびパッチを自動的に適用します。

## イベントとトリガー
<a name="gettingstarted-concepts-event"></a>

Lambda コンソール、[AWS CLI](https://aws.amazon.com/cli/)、[AWS Software Development Kit (SDK)](https://aws.amazon.com/developer/tools/) のいずれかを使用し、Lambda 関数を直接呼び出すこともできます。本番稼働用アプリケーションでは、特定のイベントに応じて、関数が別の AWS のサービス によって呼び出されるのが一般的です。例えば、項目が Amazon DynamoDB テーブルに追加されるたびに関数を実行する必要があるとします。

関数がイベントに応答するようにするには、**トリガー**を設定します。トリガーは関数をイベントソースに接続します。関数には複数のトリガーを設定できます。イベントが発生すると、Lambda は JSON ドキュメント形式のイベントデータを受信し、コードが処理できるオブジェクトに変換します。イベントに次の JSON 形式を定義すると、Lambda ランタイムはこの JSON ドキュメントをオブジェクトに変換してから関数のハンドラに渡します。

**Example カスタム Lambda イベント**  

```
{
  "Location": "SEA",
  "WeatherData":{
    "TemperaturesF":{
      "MinTempF": 22,
      "MaxTempF": 78
    },
    "PressuresHPa":{
      "MinPressureHPa": 1015,
      "MaxPressureHPa": 1027
    }
  }
}
```

Amazon Kinesis や Amazon SQS といったストリーミングサービスとキューサービスでは、標準トリガーの代わりに[イベントソースマッピング](invocation-eventsourcemapping.md)を使用します。イベントソースマッピングは、ソースをポーリングして新しいデータを検索し、レコードをまとめてバッチ処理し、バッチイベントで関数を呼び出します。詳細については、「[イベントソースマッピングと直接トリガーの違い](invocation-eventsourcemapping.md#eventsourcemapping-trigger-difference)」を参照してください。

トリガーの仕組みを理解するには、[Amazon S3 トリガーの使用](with-s3-example.md)に関するチュートリアルから始めるか、トリガーの使用に関する一般的な概要と Lambda コンソールを使用したトリガーの作成手順を「[他のサービスの統合](lambda-services.md)」で確認してください。

## Lambda のアクセス許可とロール
<a name="gettingstarted-concepts-permissions"></a>

Lambda の場合、設定する必要がある[アクセス許可](permissions-granting-access.md)には 2 つの主なタイプがあります。
+ 関数が他の AWS のサービスにアクセスするために必要なアクセス許可
+ 他のユーザーや AWS のサービスが関数にアクセスするために必要なアクセス許可

次のセクションでは、これらのアクセス許可タイプの両方について説明し、最小特権のアクセス許可を適用するためのベストプラクティスについて説明します。

### 関数がその他の AWS リソースにアクセスするためのアクセス許可
<a name="gettingstarted-concepts-permissions-role"></a>

多くの場合、Lambda 関数はその他の AWS リソースにアクセスし、アクションを実行する必要があります。例えば、関数は DynamoDB テーブルから項目を読み取ったり、オブジェクトを S3 バケットに保存したり、Amazon SQS キューに書き込んだりすることがあります。これらのアクションを実行するために関数に必要なアクセス許可を付与するには、*[実行ロール](lambda-intro-execution-role.md)*を使用します。

Lambda 実行ロールは特別な種類の AWS Identity and Access Management (IAM) [ロール](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html)のであり、*ポリシー*で定義された特定のアクセス許可が関連付けられているアカウントで作成する ID です。

すべての Lambda 関数には実行ロールが必要であり、1 つのロールが複数の関数によって使用できます。関数が呼び出されると、Lambda は関数の実行ロールを引き受け、ロールのポリシーで定義されたアクションを実行するアクセス許可が付与されます。

Lambda コンソールで関数を作成するとき、Lambda は関数に対して自動的に実行ロールを作成します。ロールのポリシーは、Amazon CloudWatch Logs にログ出力を書き込むために、関数に基本的なアクセス許可を付与します。その他の AWS リソースにアクションを実行するためのアクセス許可を関数に付与するには、ロールを編集して追加のアクセス許可を追加する必要があります。アクセス許可を追加する最も簡単な方法は、AWS [マネージドポリシー](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html#aws-managed-policies)を使用することです。マネージドポリシーは AWS によって作成および管理され、多くの一般的なユースケースにアクセス許可を付与します。例えば、関数が DynamoDB テーブルに CRUD オペレーションを実行する場合、[AmazonDynamoDBFullAccess](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AmazonDynamoDBFullAccess.html) ポリシーをロールに追加できます。

### 他のユーザーとリソースが関数にアクセスするためのアクセス許可
<a name="gettingstarted-concepts-permissions-resource-based"></a>

Lambda 関数にアクセスするために他の AWS のサービスアクセス許可を付与するには、*[リソースベースのポリシー](access-control-resource-based.md)*を使用します。IAM では、リソースベースのポリシーがリソース (この場合は Lambda 関数) にアタッチされ、リソースにアクセスできるユーザーおよび許可されるアクションを定義します。

別の AWS のサービスがトリガーを介して関数を呼び出すには、関数のリソースベースのポリシーが、そのサービスに `lambda:InvokeFunction` アクションを使用するためのアクセス許可を付与する必要があります。コンソールを使用してトリガーを作成した場合、Lambda はユーザーに代わってこのアクセス許可を自動的に追加します。

他の AWS ユーザーに関数へのアクセス許可を付与するには、別の AWS のサービスまたはリソースの場合とまったく同じ方法で、関数のリソースベースのポリシーでこれを定義できます。ユーザーに関連付けられている *[ID ベースのポリシー](access-control-identity-based.md)*を使用することもできます。

### Lambda のアクセス許可のベストプラクティス
<a name="gettingstarted-concepts-permissions-best-practice"></a>

IAM ポリシーを使用してアクセス許可を設定する際、タスクの実行に必要なアクセス許可のみを付与することが[セキュリティ上のベストプラクティス](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html)です。これは*最小特権*の原則と呼ばれます。関数にアクセス許可の付与を開始するには、AWS マネージドポリシーの使用を選択できます。マネージドポリシーは、タスクを実行するためにアクセス許可を付与するうえで最も迅速で簡単な方法ですが、不要なアクセス許可が他にも含まれる場合もあります。初期の開発からテストおよび本番稼働に移行する際は、独自の[カスタマー管理ポリシー](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html#customer-managed-policies)を定義することで、必要なアクセス許可のみに減らすことをお勧めします。

リソースベースのポリシーを使用し、関数にアクセスするためのアクセス許可を付与するときにも、同じ原則が適用されます。例えば、関数を呼び出すアクセス許可を Amazon S3 に付与する場合、S3 サービスに一括のアクセス許可を付与するのではなく、個々のバケットまたは特定の AWS アカウントのバケットへのアクセスを制限することが、ベストプラクティスです。

# Lambda を使用したコードの実行
<a name="concepts-how-lambda-runs-code"></a>

Lambda 関数を記述する際、独自のサーバーレス環境で実行するコードを作成します。Lambda が実際にコードを実行する方法を理解するには、コードが Lambda とやり取りする方法を定義するプログラミングモデルと、Lambda がコードのランタイム環境を管理する方法を決定する実行環境ライフサイクルの 2 つが重要となります。

## Lambda プログラミングモデル
<a name="concepts-progmodel-overview"></a>

Python、Java、その他のサポートされている言語で記述しているかを問わず、Lambda がコードと連携するための共通のルールセットとしてモデル関数をプログラミングします。プログラミングモデルには、ランタイムとハンドラーが含まれています。

**標準関数の場合**

1. Lambda はイベントを受け取ります。

1. Lambda はランタイムを使用して、コードで使用できる形式でイベントを準備します。

1. ランタイムは、フォーマットされたイベントをハンドラーに送信します。

1. ハンドラーは、記述したコードを使用してイベントを処理します。

**耐久性のある関数の場合**

1. Lambda はイベントを受け取る

1. ランタイムはイベントと DurableContext の両方を準備します

1. ハンドラーは次のことができます。
   + 自動チェックポイントを使用してステップを処理する
   + リソースを消費せずに実行を一時停止する
   + 最後に成功したチェックポイントから再開する
   + ステップ間で状態を維持する

このモデルで重要なのは*ハンドラー*であり、Lambda がコードによって処理されるイベントを送信します。これをコードへのエントリポイントと考えてください。Lambda はイベントを受信すると、このイベントと一部のコンテキスト情報をハンドラーに渡します。次に、ハンドラーはコードを実行してこれらのイベントを処理します。例として、Amazon S3 へのファイルアップロード、画像分析、データベース更新などが挙げられます。コードがイベントの処理を完了すると、ハンドラーは次のイベントを処理する準備が整います。

## Lambda 実行モデル
<a name="concepts-exec-env-overview"></a>

プログラミングモデルは Lambda がコードとやり取りする方法を定義しますが、実行環境は Lambda が関数を実際に実行する場所です。関数専用に作成された安全で分離されたコンピューティングスペースです。

**各環境は、標準関数と耐久性のある関数によって異なるライフサイクルに従います。**

**標準関数 (最大 15 分):**

1. **初期化:** 環境セットアップとコードの読み込み

1. **呼び出し:** 関数コードの単一実行

1. **シャットダウン:** 環境クリーンアップ

**耐久性のある関数 (最大 1 年):**

1. **初期化:** 環境と耐久性のある状態のセットアップ

1. **呼び出し:** 自動チェックポイントを使用した複数ステップ

1. **待機状態:** リソースを消費せずに実行を一時停止

1. **再開:** 最後のチェックポイントから再開

1. **シャットダウン:** 耐久性のある状態のクリーンアップ

この環境は、関数の実行の重要な側面を担っています。関数にメモリと一時的なストレージ用の `/tmp` ディレクトリを提供します。**耐久性のある関数では、以下の内容も管理します。**
+ ステップ間の自動的な状態永続性
+ チェックポイントのストレージと復旧
+ 待機状態の調整
+ 長時間の実行での進捗状況の追跡

# Lambda プログラミングモデルの概要
<a name="foundation-progmodel"></a>

Lambda には、最大 15 分間実行される標準関数と、最大 1 年間実行できる Durable Functions の 2 つのプログラミングモデルがあります。どちらも主要概念を共有しますが、Durable Functions は長時間実行されるステートフルワークフローを実現する機能を追加します。

Lambda では、すべてのランタイムに共通のプログラミングモデルを提供しています。プログラミングモデルとは、コードと Lambda システムとの間のインターフェイスを定義するものです。関数設定の*ハンドラ*を定義して、関数へのエントリポイントを Lambda に伝えます。ランタイムは、呼び出し*イベント*、および関数名やリクエスト ID などの*コンテキスト*を含むオブジェクトをハンドラーに渡します。

**Durable Functions の場合、ハンドラーは以下を提供する DurableContext オブジェクトも受信します。**
+ step() によるチェックポイント機能
+ wait() と waitForCallback() による待機状態管理
+ 呼び出し間の状態の自動保持

ハンドラーが最初のイベントの処理を終了すると、ランタイムは別のイベントを送信します。Durable Functions の場合、ハンドラーはステップ間で実行を一時停止でき、関数が再開すると Lambda は自動的に状態を保存および復元します。関数のクラスはメモリ内にとどまるため、*初期化コード*において、ハンドラーメソッドの外部で宣言されたクライアントおよび変数は再利用が可能です。後続のイベントの処理時間を短縮するには、初期化中に AWS SDK クライアントなどの再利用可能なリソースを作成します。初期化されると、関数の各インスタンスは数千件のリクエストを処理できます。

関数は、`/tmp` ディレクトリのローカルストレージにもアクセスできます。これは複数の呼び出しに使用できる一時的なキャッシュです。詳細については、「[実行環境](lambda-runtime-environment.md)」を参照してください。

[AWS X-Ray トレース](services-xray.md)が有効な場合、ランタイムは初期化と実行のために、別個のサブセグメントを記録します。

ランタイムは、関数からのログ出力をキャプチャし、Amazon CloudWatch Logs に送信します。ランタイムは、関数の出力をログに記録するだけでなく、関数の呼び出しの開始時と終了時にエントリも記録します。これには、リクエスト ID、請求期間、初期化期間、およびその他の詳細を含むレポートログが含まれます。関数によりエラーがスローされた場合、そのエラーは、ランタイムにより呼び出し元に返信されます。

**注記**  
ログ記録は、[CloudWatch Logs クォータ](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/cloudwatch_limits_cwl.html)の対象となります。ログデータは、スロットリングが原因で失われることがあります。また、場合によっては、関数のインスタンス停止時に失われることがあります。

**Durable Functions の主な違い:**
+ 状態はステップ間で自動的に保持されます
+ 関数はリソースを消費せずに実行を一時停止できます
+ ステップは失敗すると自動的に再試行される
+ チェックポイントを通じて進行状況を追跡する

Lambda は、需要の増加に応じて追加のインスタンスを実行し、需要の減少に応じてインスタンスを停止することで関数をスケーリングします。このモデルは、次のようなアプリケーションアーキテクチャにおいてばらつきが生じます。
+ 特に明記されていない限り、受信リクエストは、順不同または同時に処理されます。
+ 関数のインスタンスが長く存続することを想定せず、アプリケーションの状態を別の場所に保存します。
+ ローカルストレージとクラスレベルのオブジェクトを使用することで、パフォーマンスを向上させられます。その場合でも、デプロイパッケージのサイズと実行環境に転送するデータの量は最小限に抑えてください。

プログラミング言語別のプログラミングモデルの実践的な入門ガイドについては、以下の章を参照してください。
+ [Node.js による Lambda 関数の構築](lambda-nodejs.md)
+ [Python による Lambda 関数の構築](lambda-python.md)
+ [Ruby による Lambda 関数の構築](lambda-ruby.md)
+ [Java による Lambda 関数の構築](lambda-java.md)
+ [Go による Lambda 関数の構築](lambda-golang.md)
+ [C\$1 による Lambda 関数の構築](lambda-csharp.md)
+ [PowerShell による Lambda 関数の構築](lambda-powershell.md)

# Lambda 実行環境のライフサイクルの概要
<a name="lambda-runtime-environment"></a>

Lambda 実行環境は、標準関数 (最大 15 分) と Durable Functions (最大 1 年) の両方をサポートします。どちらも同じ基本的なライフサイクルを共有しますが、Durable Functions は長時間実行されるワークフローに状態管理機能を追加します。

 Lambda は、実行環境で関数を呼び出します。これにより、安全で分離されたランタイム環境が提供されます。実行環境は、関数の実行に必要なリソースを管理します。また、関数のランタイム、および関数に関連付けられた[外部拡張機能](lambda-extensions.md)のライフサイクルサポートも提供します。

**Durable Functions の場合、実行環境には以下の追加コンポーネントが含まれます。**
+ ステップ間の状態永続性
+ チェックポイント管理
+ 待機状態の調整
+ 進捗状況追跡

**Lambda マネージドインスタンスの実行環境**  
[Lambda マネージドインスタンス](lambda-managed-instances-execution-environment.md)を使用している場合、実行環境は Lambda (デフォルト) 関数と比較して重要な違いがあります。マネージドインスタンスは同時呼び出しをサポートし、別のライフサイクルモデルを使用して、顧客所有のインフラストラクチャで実行します。マネージドインスタンス実行環境の詳細については、「[Lambda マネージドインスタンスの実行環境について理解する](lambda-managed-instances-execution-environment.md)」を参照してください。

関数のランタイムは、[ランタイム API](runtimes-api.md) を使用して Lambda と通信します。拡張機能は、[拡張機能 API](runtimes-extensions-api.md) を使用して Lambda と通信します。拡張機能は、[Telemetry API](telemetry-api.md) を使用することで、関数からログメッセージとその他のテレメトリを受け取ることもできます。



![\[実行環境のアーキテクチャ図。\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/telemetry-api-concept-diagram.png)


Lambda 関数を作成する際に、関数に許可するメモリ容量や最大実行時間など、設定情報を指定します。Lambda はこの情報を使用して実行環境をセットアップします。

関数のランタイムと各外部拡張機能は、実行環境内で実行されるプロセスです。アクセス許可、リソース、認証情報、および環境変数は、関数と拡張機能の間で共有されます。

**Topics**
+ [

## Lambda 実行環境のライフサイクル
](#runtimes-lifecycle)
+ [

## コールドスタートとレイテンシー
](#cold-start-latency)
+ [

## プロビジョニングされた同時実行によるコールドスタートの減少
](#cold-starts-pc)
+ [

## 静的初期化の最適化
](#static-initialization)

## Lambda 実行環境のライフサイクル
<a name="runtimes-lifecycle"></a>

![\[Lambda のライフサイクルフェーズ: Init、Invoke、Shutdown\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/Overview-Successful-Invokes.png)


各フェーズは、ランタイムと、登録されているすべての拡張機能に Lambda を送信するイベントから始まります。ランタイムと各拡張機能は、`Next` API リクエストを送信することで完了を示します。Lambda は、ランタイムと各拡張機能が完了して保留中のイベントがなくなると、実行環境をフリーズします。

**Durable Functions のライフサイクルフェーズは次のとおりです。**
+ **初期化:** 標準初期化と永続的な状態のセットアップ
+ **呼び出し:** 自動チェックポイントを使用して複数のステップ実行を含めることができる
+ **待機:** 関数はリソースを消費せずに実行を一時停止できる
+ **再開:** 最後のチェックポイントから関数が再起動する
+ **シャットダウン:** 永続的な状態とリソースのクリーンアップ

**Topics**
+ [

### 初期化フェーズ
](#runtimes-lifecycle-ib)
+ [

### 初期化フェーズ中の失敗
](#runtimes-lifecycle-init-errors)
+ [

### 復元フェーズ (Lambda SnapStart のみ)
](#runtimes-lifecycle-restore)
+ [

### 呼び出しフェーズ
](#runtimes-lifecycle-invoke)
+ [

### 呼び出しフェーズ中の失敗
](#runtimes-lifecycle-invoke-with-errors)
+ [

### シャットダウンフェーズ
](#runtimes-lifecycle-shutdown)

### 初期化フェーズ
<a name="runtimes-lifecycle-ib"></a>

`Init` フェーズでは、Lambda は次の 3 つのタスクを実行します。
+ すべての拡張機能を起動する (`Extension init`)
+ ランタイムをブートストラップする (`Runtime init`)
+ 関数の静的コード (`Function init`) を実行する
+ 任意の before-checkpoint [ランタイムフック](snapstart-runtime-hooks.md)を実行する (Lambda SnapStart のみ)

この `Init` フェーズは、ランタイムとすべての拡張機能が `Next` API リクエストを送信して準備完了を示したときに終了します。`Init` フェーズは 10 秒に制限されています。3 つのタスクすべてが 10 秒以内に完了しない場合、Lambda は最初の関数呼び出し時に、設定された関数タイムアウトで `Init` フェーズを再試行します。

[Lambda SnapStart](snapstart.md) がアクティブ化されると、関数バージョンの発行時に `Init` フェーズが開始されます。Lambda は、初期化された実行環境のメモリとディスク状態のスナップショットを保存し、暗号化されたスナップショットを永続化して、低レイテンシーアクセスのためにスナップショットをキャッシュします。チェックポイント前の[ランタイムフック](snapstart-runtime-hooks.md)がある場合、コードは `Init` フェーズの最後に実行されます。

**注記**  
10 秒のタイムアウトは、プロビジョニングされた同時実行、SnapStart または Lambda マネージドインスタンスを使用している関数には適用されません。プロビジョニングされた同時実行関数、SnapStart 関数、マネージドインスタンス関数の場合、初期化コードは最大 15 分間実行できます。制限時間は 130 秒、または設定されている関数のタイムアウト (最大 900 秒) のいずれか長い方です。

[プロビジョニング済み同時実行](https://docs.aws.amazon.com/lambda/latest/dg/provisioned-concurrency.html)を使用する場合、関数の PC 設定を行う際、Lambda は実行環境を初期化します。また Lambda は、初期化された実行環境が呼び出し前に常に使用できるようにします。関数の呼び出しフェーズと初期化フェーズの間に予期しないギャップが発生する場合があります。関数のランタイムとメモリ設定によっては、初期化された実行環境での最初の呼び出しでレイテンシーの変動が発生する場合があります。

オンデマンド同時実行を使用する関数の場合、Lambda は呼び出しリクエストの前に実行環境を初期化することがあります。これが発生すると、関数の初期化フェーズと呼び出しフェーズの間に時間のギャップが発生することがあります。この動作に依存しないことをお勧めします。

### 初期化フェーズ中の失敗
<a name="runtimes-lifecycle-init-errors"></a>

`Init` フェーズ中に関数がクラッシュするかタイムアウトすると、Lambda は `INIT_REPORT` ログにエラー情報を出力します。

**Example — タイムアウトの INIT\$1REPORT ログ**  

```
INIT_REPORT Init Duration: 1236.04 ms Phase: init Status: timeout
```

**Example — 拡張が失敗したときの INIT\$1REPORT ログ**  

```
INIT_REPORT Init Duration: 1236.04 ms Phase: init Status: error Error Type: Extension.Crash
```

`Init` フェーズが成功した場合、[SnapStart](snapstart.md) または[プロビジョニングされた同時実行数](provisioned-concurrency.md)が有効になっていない限り、Lambda は `INIT_REPORT` ログを出力しません。SnapStart 関数およびプロビジョニングされた同時実行関数は常に `INIT_REPORT` を出力します。詳細については、「[Lambda SnapStart のモニタリング](snapstart-monitoring.md)」を参照してください。

### 復元フェーズ (Lambda SnapStart のみ)
<a name="runtimes-lifecycle-restore"></a>

[SnapStart](snapstart.md) 関数を初めて呼び出し、その関数がスケールアップすると、Lambda は関数をゼロから初期化するのではなく、永続化されたスナップショットから新しい実行環境を再開します。復元後の[ランタイムフック](snapstart-runtime-hooks.md)がある場合、コードは `Restore` フェーズの最後に実行されます。ユーザーには、復元後のランタイムフックの所要時間分の料金が請求されます。タイムアウト制限 (10 秒) 内にランタイムがロードされ、復元後のランタイムフックが完了される必要があります。その時間を超えると、SnapStartTimeoutException が発生します。`Restore` フェーズが完了すると、Lambda が関数ハンドラーを呼び出します ([呼び出しフェーズ](#runtimes-lifecycle-invoke))。

#### 復元フェーズ中の失敗
<a name="runtimes-lifecycle-restore-errors"></a>

`Restore` フェーズが失敗した場合、Lambda は `RESTORE_REPORT` ログにエラー情報を出力します。

**Example — タイムアウトの RESTORE\$1REPORT ログ**  

```
RESTORE_REPORT Restore Duration: 1236.04 ms Status: timeout
```

**Example — ランタイムフック障害の RESTORE\$1REPORT ログ**  

```
RESTORE_REPORT Restore Duration: 1236.04 ms Status: error Error Type: Runtime.ExitError
```

`RESTORE_REPORT` ログの詳細については、「[Lambda SnapStart のモニタリング](snapstart-monitoring.md)」を参照してください。

### 呼び出しフェーズ
<a name="runtimes-lifecycle-invoke"></a>

`Next` API リクエストに応答して Lambda 関数が呼び出されると、Lambda はランタイムと各拡張機能に `Invoke` イベントを送信します。

関数のタイムアウト設定は、`Invoke` フェーズ全体の所要時間を制限します。例えば、関数のタイムアウトを 360 秒に設定した場合、関数とすべての拡張機能は 360 秒以内に完了する必要があります。独立した呼び出し後フェーズはないことに注意してください。所要時間は、すべての呼び出し時間 (ランタイム \$1 拡張機能) の合計であり、関数とすべての拡張機能の実行が終了するまで計算されません。

呼び出しフェーズはランタイム後に終了し、すべての拡張機能は `Next` API リクエストを送信して、完了したことを示します。

### 呼び出しフェーズ中の失敗
<a name="runtimes-lifecycle-invoke-with-errors"></a>

Lambda 関数が `Invoke` フェーズ中にクラッシュするかタイムアウトすると、Lambda は実行環境をリセットします。次の図は、呼び出しに失敗した場合の Lambda 実行環境の動作を示しています。

![\[実行環境の例: Init、Invoke、Invoke with Error、Invoke、Shutdown\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/Overview-Invoke-with-Error.png)


前示の図では次のとおりです。
+ 最初のフェーズは、エラーなしで実行される **INIT** フェーズです。
+ 2 番目のフェーズは、エラーなしで実行される **INVOKE** フェーズです。
+ ある時点で、関数が呼び出しに失敗したとします (一般的な失敗の原因には、関数のタイムアウト、ランタイムエラー、メモリの枯渇、VPC 接続の問題、アクセス許可エラー、同時実行制限、さまざまな設定の問題などがあります)。考えられる呼び出し失敗の全リストについては、「[Lambda での呼び出しに関する問題のトラブルシューティング](troubleshooting-invocation.md)」を参照してください。**INVOKE WITH ERROR** というラベルの付いた 3 番目のフェーズは、このシナリオを示しています。これが発生すると、Lambda サービスはリセットを実行します。リセットは `Shutdown` イベントのように動作します。まず、Lambda はランタイムをシャットダウンし、登録された各外部拡張機能に `Shutdown` イベントを送信します。イベントには、シャットダウンの理由が含まれます。この環境が新しい呼び出しに使用される場合、Lambda は次の呼び出しとともに拡張機能とランタイムを再び初期化します。

  Lambda のリセットでは、次の初期化フェーズより前の `/tmp` ディレクトリコンテンツはクリアされないことにご注意ください。この動作は、通常のシャットダウンフェーズと一致しています。
**注記**  
AWS は現在、Lambda サービスに変更を実装しています。これらの変更により、AWS アカウント のさまざまな Lambda 関数によって出力されるシステムログメッセージとトレースセグメントの構造と内容にわずかな違いが生じる場合があります。  
関数のシステムログ設定がプレーンテキストに設定されている場合、この変更は、関数の呼び出しに障害が発生した際に CloudWatch Logs でキャプチャされたログメッセージに影響します。次の例は、古い形式と新しい形式の両方でのログ出力を示しています。  
これらの変更は今後数週間に実装され、中国および GovCloud リージョンを除くすべての AWS リージョンのすべての関数は、新しい形式のログメッセージとトレースセグメントを使用するように移行されます。

    
**Example CloudWatch Logs ログ出力 (ランタイムまたは拡張機能のクラッシュ) - 旧形式**  

  ```
  START RequestId: c3252230-c73d-49f6-8844-968c01d1e2e1 Version: $LATEST
  RequestId: c3252230-c73d-49f6-8844-968c01d1e2e1 Error: Runtime exited without providing a reason
  Runtime.ExitError
  END RequestId: c3252230-c73d-49f6-8844-968c01d1e2e1
  REPORT RequestId: c3252230-c73d-49f6-8844-968c01d1e2e1 Duration: 933.59 ms Billed Duration: 934 ms Memory Size: 128 MB Max Memory Used: 9 MB
  ```  
**Example CloudWatch Logs ログ出力 (関数タイムアウト) - 旧形式**  

  ```
  START RequestId: b70435cc-261c-4438-b9b6-efe4c8f04b21 Version: $LATEST
  2024-03-04T17:22:38.033Z b70435cc-261c-4438-b9b6-efe4c8f04b21 Task timed out after 3.00 seconds
  END RequestId: b70435cc-261c-4438-b9b6-efe4c8f04b21
  REPORT RequestId: b70435cc-261c-4438-b9b6-efe4c8f04b21 Duration: 3004.92 ms Billed Duration: 3117 ms Memory Size: 128 MB Max Memory Used: 33 MB Init Duration: 111.23 ms
  ```

  CloudWatch Logs の新しい形式には、`REPORT` 行に `status` フィールドが追加で含まれます。ランタイムまたは拡張機能のクラッシュの場合、`REPORT` 行に `ErrorType` フィールドも含まれます。

    
**Example CloudWatch Logs ログ出力 (ランタイムまたは拡張機能のクラッシュ) - 新形式**  

  ```
  START RequestId: 5b866fb1-7154-4af6-8078-6ef6ca4c2ddd Version: $LATEST
  END RequestId: 5b866fb1-7154-4af6-8078-6ef6ca4c2ddd
  REPORT RequestId: 5b866fb1-7154-4af6-8078-6ef6ca4c2ddd Duration: 133.61 ms Billed Duration: 214 ms Memory Size: 128 MB Max Memory Used: 31 MB Init Duration: 80.00 ms Status: error Error Type: Runtime.ExitError
  ```  
**Example CloudWatch Logs ログ出力 (関数タイムアウト) - 新形式**  

  ```
  START RequestId: 527cb862-4f5e-49a9-9ae4-a7edc90f0fda Version: $LATEST
  END RequestId: 527cb862-4f5e-49a9-9ae4-a7edc90f0fda
  REPORT RequestId: 527cb862-4f5e-49a9-9ae4-a7edc90f0fda Duration: 3016.78 ms Billed Duration: 3101 ms Memory Size: 128 MB Max Memory Used: 31 MB Init Duration: 84.00 ms Status: timeout
  ```
+  4 番目のフェーズは、呼び出しが失敗した直後の **INVOKE** フェーズを表します。ここで、Lambda は **INIT** フェーズを再実行して環境を再び初期化します。これは、*抑制された初期化*と呼ばれます。抑制された初期化が発生した場合、Lambda は CloudWatch Logs で追加の **INIT** フェーズを明示的にレポートしません。代わりに、REPORT 行の期間に追加の **INIT** 期間 \$1 **INVOKE** 期間が含まれる場合があります。例えば、CloudWatch で次のログが表示されたとします。

  ```
  2022-12-20T01:00:00.000-08:00 START RequestId: XXX Version: $LATEST 
  2022-12-20T01:00:02.500-08:00 END RequestId: XXX 
  2022-12-20T01:00:02.500-08:00 REPORT RequestId: XXX Duration: 3022.91 ms 
  Billed Duration: 3000 ms Memory Size: 512 MB Max Memory Used: 157 MB
  ```

  この例では、REPORT タイムスタンプと START タイムスタンプの差は 2.5 秒です。これは、報告された 3022.91 ミリ秒の期間とは一致しません。なぜなら、Lambda が実行した追加の **INIT** (抑制された init) が考慮されていないからです。この例では、実際の **INVOKE** フェーズでは 2.5 秒かかったと推測できます。

  この動作に関するより多くのインサイトを得るために、[Telemetry API を使用して拡張機能のリアルタイムテレメトリデータにアクセスする](telemetry-api.md) を使用できます。Telemetry API は、抑制された初期化が呼び出しフェーズの間で発生するたびに、`phase=invoke` の `INIT_START`、`INIT_RUNTIME_DONE`、および `INIT_REPORT` イベントを発行します。
+ 5 番目のフェーズは、エラーなしで実行される **SHUTDOWN** フェーズを表します。

### シャットダウンフェーズ
<a name="runtimes-lifecycle-shutdown"></a>

Lambda は、ランタイムをシャットダウンしようとする際、`Shutdown` イベントを登録された各外部拡張機能に送信します。拡張機能は、この時間を最終的なクリーンアップタスクに使用できます。`Shutdown` イベントは、`Next` API リクエストに対するレスポンスです。

**所要時間の制限**: `Shutdown` フェーズの最大所要時間は、登録された拡張機能の設定によって異なります。
+ 0 ms – 登録された拡張機能を持たない関数
+ 500 ms - 登録された内部拡張機能を持つ関数
+ 2000 ms - 登録された外部拡張機能を 1 つ以上持つ関数

ランタイムまたは拡張機能が制限内で `Shutdown` イベントに応答しない場合、Lambda は `SIGKILL` の通知を使用してプロセスを終了します。

関数とすべての拡張機能が完了した後、Lambda は別の関数の呼び出しを想定して、実行環境をしばらく維持します。ただし、Lambda は数時間ごとに実行環境を終了し、ランタイムの更新とメンテナンスを許可します。継続的に呼び出される関数であっても、この終了は発生します。実行環境が無期限に保持されると想定すべきではありません。詳細については、「[関数にステートレスの実装](concepts-application-design.md#statelessness-functions)」を参照してください。

関数が再び呼び出されると、再利用のため、Lambda によって環境が解凍されます。実行環境の再利用には、次のような意味があります。
+ 関数ハンドラーメソッドの外部で宣言されたオブジェクトは、初期化されたままとなり、関数が再度呼び出されると追加の最適化を提供します。例えば、Lambda 関数がデータベース接続を確立する場合、連続した呼び出しでは接続を再確立する代わりに元の接続が使用されます。新しい接続を作成する前に、接続が存在するかどうかを確認するロジックをコードに追加することをお勧めします。
+ 各実行環境は、`/tmp` ディレクトリに 512 MB と 10,240 MB 間を 1 MB 刻みで提供します。ディレクトリのコンテンツは、実行環境が停止された際に維持され、複数の呼び出しに使用できる一時的なキャッシュを提供します。キャッシュに保存したデータが存在するかどうかを確認するための追加コードを追加できます。デプロイのサイズ制限の詳細については、「[Lambda クォータLambda クォータ](gettingstarted-limits.md)」を参照してください。
+ Lambda 関数によって開始され、関数が終了したときに完了しなかったバックグラウンドプロセスまたはコールバックは、Lambda 関数が実行環境を再利用したときに再開します。コードのバックグラウンド処理またはコールバックは、コード終了までに完了させてください。

## コールドスタートとレイテンシー
<a name="cold-start-latency"></a>

Lambda が Lambda API を介して関数を実行するリクエストを受信すると、サービスはまず実行環境を準備します。この初期化フェーズ中、サービスはコードをダウンロードし、環境を起動して、メインハンドラーの外部で初期化コードを実行します。最後に、Lambda はハンドラーコードを実行します。

![\[パフォーマンス最適化の図 1\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/perf-optimize-figure-1.png)


この図では、コードのダウンロードおよび環境の設定に関する最初の 2 つのステップは、頻繁に「コールドスタート」と呼ばれます。[この時間には課金されません](https://aws.amazon.com/blogs/compute/aws-lambda-standardizes-billing-for-init-phase/)が、全体的な呼び出し期間にレイテンシーが発生します。

呼び出しが完了すると、実行環境はフリーズされます。リソース管理およびパフォーマンスを向上させるため、Lambda はある期間中に実行環境を保持します。この間、同じ関数に対して別のリクエストを送信した場合、Lambda は環境を再利用できます。この 2 番目のリクエストは、実行環境が既に完全にセットアップされているため、通常はより迅速に終了します。これは、「ウォームスタート」と呼ばれます。

通常、コールドスタートは呼び出しの 1% 未満で発生します。コールドスタートの時間は 100 ミリ秒未満から 1 秒以上までさまざまです。一般的に、コールドスタートは本番稼働ワークロードよりも、開発およびテスト機能で一般的です。これは、通常、開発関数とテスト関数の呼び出し頻度が低いためです。

## プロビジョニングされた同時実行によるコールドスタートの減少
<a name="cold-starts-pc"></a>

ワークロードに予測可能な関数開始時間が必要な場合、レイテンシーを可能な限り最小限に抑えるため、[プロビジョニングされた同時実行数](provisioned-concurrency.md)が推奨されるソリューションです。この機能は実行環境を事前に初期化し、コールドスタートを減らします。

例えば、プロビジョニングされた同時実行数が 6 の関数には、事前ウォーミングされた実行環境が 6 つあります。

![\[パフォーマンス最適化の図 4\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/perf-optimize-figure-4.png)


## 静的初期化の最適化
<a name="static-initialization"></a>

静的初期化は、ハンドラーコードが関数で実行を開始する前に発生します。これは指定する初期化コードであり、メインハンドラーの外部にあります。このコードはライブラリおよび依存関係のインポート、設定のセットアップ、他のサービスへの接続の初期化によく使用されます。

次の Python の例では、呼び出し中に `lambda_handler` 関数が実行される前に、インポート、モジュールの設定、初期化フェーズ中に Amazon S3 クライアントを作成する方法が示されます。

```
import os
import json
import cv2
import logging
import boto3

s3 = boto3.client('s3')
logger = logging.getLogger()
logger.setLevel(logging.INFO)

def lambda_handler(event, context):

  # Handler logic...
```

関数の実行前のレイテンシーの最大の原因は、初期化コードにあります。このコードは、新しい実行環境が初めて作成されたときに実行されます。呼び出しでウォーム実行環境を使用している場合、初期化コードは再度実行されません。初期化コードのレイテンシーに影響する要因には、次の内容が含まれます。
+ 関数パッケージのサイズ (インポートされたライブラリと依存関係、および Lambda レイヤーの観点から)。
+ コードと初期化作業の量。
+ 接続やその他のリソースの設定におけるライブラリやその他のサービスのパフォーマンス。

開発者が静的初期化レイテンシーを最適化するために実行できるステップは多数あります。関数に多数のオブジェクトと接続がある場合、単一の関数を複数の特化した関数にリアーキテクトできる場合があります。これらはそれぞれより小さく、初期化コードが少なくなります。

関数は、必要なライブラリと依存関係のみをインポートすることが重要です。例えば、AWS SDK で Amazon DynamoDB のみを使用する場合、SDK 全体ではなく単一のサービスを要求できます。次の 3 つの例を比較します。

```
// Instead of const AWS = require('aws-sdk'), use:
const DynamoDB = require('aws-sdk/clients/dynamodb')

// Instead of const AWSXRay = require('aws-xray-sdk'), use:
const AWSXRay = require('aws-xray-sdk-core')

// Instead of const AWS = AWSXRay.captureAWS(require('aws-sdk')), use:
const dynamodb = new DynamoDB.DocumentClient()
AWSXRay.captureAWSClient(dynamodb.service)
```

静的初期化は、関数が同じ実行環境に複数の呼び出しで接続を再利用できるように、データベース接続を開く場所としても最適である場合がよくあります。ただし、関数内の特定の実行パスでのみ使用されるオブジェクトが多数ある可能性があります。この場合、グローバルスコープで変数を遅延ロードすることで、静的初期化の時間を短縮できます。

コンテキスト固有の情報のグローバル変数は避けてください。関数に単一の呼び出しの有効期間にのみ使用されるグローバル変数があり、次の呼び出しでリセットされる場合は、ハンドラーにローカルな変数スコープを使用してください。これにより、呼び出し間でグローバル変数がリークされなくなるだけでなく、静的初期化のパフォーマンスも向上します。

# Lambda を使用したイベント駆動型アーキテクチャの作成
<a name="concepts-event-driven-architectures"></a>

イベントとは、Lambda 関数の実行をトリガーするあらゆる事象を指します。イベントは、直接呼び出し (プッシュ) とイベントソースマッピング (プル) の 2 つの方法で Lambda 関数をトリガーできます。

多くの AWS サービスは、Lambda 関数を直接呼び出すことができます。これらのサービスは、Lambda 関数にイベントを*プッシュ*します。関数をトリガーするイベントは、API Gateway を介した HTTP リクエスト、EventBridge ルールで管理されているスケジュール、AWS IoT イベント、Amazon S3 イベントなど、ほぼどのような形式でも可能です。イベントソースマッピングを使用すると、Lambda はキューまたはストリームからイベントをアクティブに取得 (または*プル*) します。サポートされているサービスからのイベントをチェックするように Lambda を設定すると、Lambda は関数のポーリングと呼び出しを処理します。

イベントは、関数に渡すと、JSON 形式で構造化されます。JSON 構造は、JSON を生成するサービスやイベントタイプによって異なります。標準の Lambda 関数の呼び出しは最大 15 分 ([耐久性のある関数](durable-functions.md)で最大 1 年) 継続することが可能ですが、Lambda は 1 秒以下の短い呼び出しに最適です。特にイベント駆動型アーキテクチャでは、各 Lambda 関数が特定の限られた命令を実行するマイクロサービスとして扱われますす。

**注記**  
イベント駆動型アーキテクチャは、ネットワークを使用して異なるシステム間で通信するため、レイテンシーが変動します。リアルタイム取引システムなどの、非常に低いレイテンシーを必要とするワークロードでは、この設計は最適な選択肢ではない場合もあります。しかし、スケーラビリティと可用性の高いワークロードや、トラフィックパターンが予測不可能なワークロードの場合は、イベント駆動型アーキテクチャがこれらの需要を満たす効果的な方法を提供できます。

**Topics**
+ [

## イベント駆動型アーキテクチャのメリット
](#event-driven-benefits)
+ [

## イベント駆動型アーキテクチャのトレードオフ
](#event-driven-tradeoffs)
+ [

## Lambda ベースのイベント駆動型アプリケーションのアンチパターン
](#event-driven-anti-patterns)

## イベント駆動型アーキテクチャのメリット
<a name="event-driven-benefits"></a>

Lambda は、イベント駆動型アーキテクチャにおいて 2 つの呼び出し方法をサポートしています。

1. 直接呼び出し (プッシュメソッド): AWS サービスは Lambda 関数を直接トリガーします。例えば、次のようになります。
   + Amazon S3 は、ファイルのアップロード時に関数をトリガーします。
   + API Gateway は、HTTP リクエストを受信すると関数をトリガーします。

1. イベントソースマッピング (プルメソッド): Lambda はイベントを取得し、関数を呼び出します。例えば、次のようになります。
   + Lambda は Amazon SQS キューからメッセージを取得し、関数を呼び出します。
   + Lambda は DynamoDB ストリームからレコードを読み取り、関数を呼び出します。

以下に説明するように、どちらの方法もイベント駆動型アーキテクチャの利点をもたらします。

### イベントによるポーリングとウェブフックの置き換え
<a name="polling-webhooks-events"></a>

従来のアーキテクチャの多くはポーリングやウェブフックのメカニズムを使用し、異なるコンポーネント間で状態を通信します。ポーリングは、新しいデータが使用可能になってからダウンストリームサービスと同期するまでに遅延があるため、更新を取得する際に非常に非効率的になる可能性があります。ウェブフックは、統合する他のマイクロサービスで常にサポートされているわけではありません。また、カスタムの認可と認証の設定が必要になる場合もあります。どちらの場合も、これらの統合方法は、開発チームによる追加の作業なしにオンデマンドでスケールするのは困難です。

![\[イベント駆動型アーキテクチャの図 7\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/event-driven-architectures-figure-7.png)


これらのメカニズムの両方をイベントに置き換えることができ、マイクロサービスを使用するために、イベントのフィルタリング、ルーティング、ダウンストリームへのプッシュを行うことができます。このアプローチにより、帯域幅の消費量、CPU 使用率、コストが低下する可能性があります。このようなアーキテクチャでは、各機能ユニットが小規模になり、コードが少なくなることが多いため、複雑さも軽減できます。

![\[イベント駆動型アーキテクチャの図 8\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/event-driven-architectures-figure-8.png)


また、イベント駆動型アーキテクチャは、ほぼリアルタイムでのシステムの設計を容易にし、組織がバッチベースの処理から脱却するためにも役立ちます。イベントはアプリケーションの状態が変更された時点で生成されるため、マイクロサービスのカスタムコードは単一のイベントの処理を扱うように設計する必要があります。スケーリングは Lambda サービスによって処理されるため、このアーキテクチャではカスタムコードを変更せずにトラフィックの大幅な増加を処理できます。イベントがスケールアップすると、イベントを処理するコンピューティングレイヤーもスケールアップします。

### 複雑さの軽減
<a name="complexity"></a>

マイクロサービスを使用すると、デベロッパーとアーキテクトは複雑なワークフローをシンプルにできます。例えば、e コマースモノリスは、個別の在庫、履行、会計のサービスを使用して、注文の承諾と支払いのプロセスに分割できます。モノリスで管理およびオーケストレーションが複雑になる可能性があるものは、イベントと非同期的に通信する一連の分離されたサービスになります。

![\[イベント駆動型アーキテクチャの図 9\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/event-driven-architectures-figure-9.png)


このアプローチにより、さまざまなレートでデータを処理するサービスを組み合わせることもできます。この例では、注文承諾のマイクロサービスは、メッセージを Amazon SQS キューにバッファリングすることで、大量の受信注文を保存できます。

通常、支払い処理サービスは支払い処理の複雑さのためにより遅く、Amazon SQS キューからのメッセージの流れが停滞する可能性があります。AWS Step Functions を使用して複雑な再試行およびエラーの処理ロジックをオーケストレーションし、数十万の注文のアクティブな支払いワークフローを調整することができます。

**代替アプローチ:** 標準プログラミング言語を使用したオーケストレーションでは、[Lambda の耐久性のある関数](durable-functions.md)を使用できます。耐久性のある関数を使用すると、自動チェックポイント設定と再試行を使用して、注文の承諾、支払い処理、通知ロジックをコードに記述できます。このアプローチは、ワークフローに主に Lambda 関数が含まれ、オーケストレーションロジックをコードに保持したい場合に適しています。

### スケーラビリティと拡張性の向上
<a name="scalability-extensibility"></a>

マイクロサービスは、通常は Amazon SNS や Amazon SQS などのメッセージングサービスに発行されるイベントを生成します。これらはマイクロサービス間の弾性バッファのように機能し、トラフィックの増加時にスケーリングを処理するために役立ちます。Amazon EventBridge などのサービスは、その後、ルールでの定義に従い、イベントの内容に応じてメッセージをフィルタリングおよびルーティングすることができます。これにより、イベントベースのアプリケーションは、モノリシックアプリケーションよりもスケーラブルになり、冗長性が向上します。

また、このシステムは非常に拡張しやすく、他のチームが注文処理や支払い処理のマイクロサービスに影響を与えることなく機能を拡張および追加することもできます。このアプリケーションは EventBridge を使用してイベントを発行することで在庫のマイクロサービスなどの既存のシステムと統合されますが、将来のアプリケーションはイベントコンシューマーとして統合することもできます。イベントプロデューサーではイベントコンシューマーが認識されないため、マイクロサービスロジックを簡素化するために役立ちます。

## イベント駆動型アーキテクチャのトレードオフ
<a name="event-driven-tradeoffs"></a>

### レイテンシーの変動
<a name="variable-latency"></a>

単一のデバイス上の同じメモリ空間内ですべてを処理できる場合があるモノリシックアプリケーションとは異なり、イベント駆動型アプリケーションはネットワーク間で通信します。この設計では、レイテンシーが変動します。レイテンシーを最小限に抑えるようにアプリケーションを設計することはできますが、モノリシックアプリケーションはほとんどの場合、スケーラビリティと可用性を犠牲にして、レイテンシーを低くするために最適化できます。

銀行の高頻度な取引用途や倉庫のミリ秒未満のロボットオートメーションなど、一貫した低レイテンシーパフォーマンスを必要とするワークロードは、イベント駆動型アーキテクチャの候補として適していません。

### 結果整合性
<a name="eventual-consistency"></a>

イベントは状態の変化を表し、特定の時点でアーキテクチャ内のさまざまなサービスを多くのイベントが通過するため、このようなワークロードは多くの場合[結果整合性](https://en.wikipedia.org/wiki/Eventual_consistency)が保たれます。これにより、トランザクションの処理、重複の処理、システムの正確な全体的な状態の決定が、より複雑になります。

一部のワークロードには、結果整合性 (現在の時間の合計注文数など) または強力な整合性の (現在の在庫など) 要件の組み合わせが含まれています。強力なデータ整合性を必要とするワークロードには、サポートするアーキテクチャパターンがあります。例えば、次のようになります。
+ DynamoDB は[強力な整合性のある読み込み](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.ReadConsistency.html)を提供できます。レイテンシーが高くなる場合があり、デフォルトモードよりも多くスループットを消費します。DynamoDB は、データ整合性を維持するために[トランザクションをサポート](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/transactions.html)することもできます。
+ Amazon RDS は [ACID プロパティ](https://en.wikipedia.org/wiki/ACID)を必要とする機能に使用できますが、リレーショナルデータベースは DynamoDB などの NoSQL データベースよりもスケーラビリティが一般的に低下します。[Amazon RDS Proxy](https://aws.amazon.com/rds/proxy/) は、Lambda 関数などのエフェメラルコンシューマーからの接続プーリングとスケーリングを管理するのに役立ちます。

イベントベースのアーキテクチャは、通常、大量のデータのバッチではなく、個々のイベントを中心に設計されています。通常、ワークフローは、複数のイベントを同時に操作するのではなく、個々のイベントまたは実行フローのステップを管理するために設計されています。サーバーレスでは、バッチ処理よりもリアルタイムのイベント処理が推奨され、バッチは多くて小さな増分更新プログラムに置き換えられます。これにより、ワークロードの可用性およびスケーラビリティが向上しますが、イベントが他のイベントを認識することが難しくなります。

### 呼び出し元に値を返す
<a name="values-callers"></a>

多くの場合、イベントベースのアプリケーションは非同期です。そのため、呼び出し元のサービスは他のサービスからのリクエストを待機せず、他の作業を続行します。これは、スケーラビリティと柔軟性を実現するイベント駆動型アーキテクチャの基本的な特性です。戻り値やワークフローの結果を渡すことが、同期実行フローよりも複雑になることを意味します。

本番システムのほとんどの Lambda 呼び出しは[非同期](invocation-async.md)であり、Amazon S3 や Amazon SQS などのサービスからのイベントに対応します。このような場合、イベントの処理の成功または失敗が、値を返すことよりも重要であることがよくあります。Lambda の[デッドレターキュー](https://docs.aws.amazon.com/lambda/latest/dg/invocation-async.html) (DLQ) などの機能は、呼び出し元に通知することなく、失敗したイベントを特定して再試行できるように提供されています。

### サービスおよび関数間のデバッグ
<a name="services-functions"></a>

イベント駆動型システムのデバッグもモノリシックアプリケーションとは異なります。さまざまなシステムやサービスがイベントを渡すため、エラーが発生したときに複数のサービスの正確な状態を記録して再現することは不可能です。サービスと関数の呼び出しごとにログファイルが異なるため、エラーの原因となった特定のイベントに何が起こったかを判断することがより複雑になる可能性があります。

イベント駆動型システムで成功するデバッグアプローチを構築するには、3 つの重要な要件があります。まず、堅牢なログ記録システムが重要です。これは AWS のサービス間で提供され、Amazon CloudWatch によって Lambda 関数に埋め込まれます。次に、これらのシステムで、ログを検索する際に役立つように、トランザクション全体の各ステップでログに記録されるトランザクション識別子がすべてのイベントにあることを確認することが重要です。

最後に、AWS X-Ray などのデバッグおよびモニタリングサービスを使用し、ログの解析および分析を自動化することを強くお勧めします。これにより、複数の Lambda 呼び出しおよびサービス間でログを使用できるため、問題の根本原因をより簡単に特定できます。トラブルシューティングに X-Ray を使用する詳細な説明については、「[トラブルシューティングのチュートリアル](lambda-troubleshooting.md)」を参照してください。

## Lambda ベースのイベント駆動型アプリケーションのアンチパターン
<a name="event-driven-anti-patterns"></a>

Lambda でイベント駆動型アーキテクチャを構築する場合は、次の一般的なアンチパターンは避けてください。これらのパターンは機能しますが、コストと複雑さが増す可能性があります。

### Lambda モノリス
<a name="monolith"></a>

Amazon EC2 インスタンスや Elastic Beanstalk アプリケーションなどの従来サーバーから移行された多くのアプリケーションでは、開発者は既存のコードを「リフトアンドシフト」します。これにより、多くの場合、すべてのイベントに対してトリガーされるすべてのアプリケーションロジックを含む単一の Lambda 関数が生成されます。基本的なウェブアプリケーションの場合、モノリシック Lambda 関数がすべての API Gateway ルートを処理し、必要なすべてのダウンストリームリソースと統合されます。

![\[イベント駆動型アーキテクチャの図 13\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/event-driven-architectures-figure-13.png)


このアプローチにはいくつかの欠点があります。
+  **パッケージサイズ** – 可能性があるすべてのコードがすべてのパスに含まれているため、Lambda 関数が非常に大きくなる場合もあります。これにより、Lambda サービスの実行が遅くなります。
+  **最小特権の強制が困難** – 関数の[実行ロール](lambda-intro-execution-role.md)は、すべてのパスに必要なすべてのリソースへのアクセスを許可する必要があり、アクセス許可が非常に広範になります。これはセキュリティ上の懸念です。機能モノリスの多くのパスには、付与されたすべてのアクセス許可は必要ありません。
+  **アップグレードが困難** - 本番システムでは、単一の関数をアップグレードするリスクが高くなり、アプリケーション全体が破損する可能性があります。Lambda 関数の単一パスのアップグレードは、関数全体のアップグレードになります。
+  **維持が困難** - モノリシックコードリポジトリであるため、複数の開発者がサービスに取り組むことが難しくなります。また、開発者の認知負荷が高まり、コードの適切なテストカバレッジを作成することが難しくなります。
+  **コードの再利用が困難** - 再利用可能なライブラリをモノリスから分離することが難しくなり、コードの再利用が難しくなります。より多くのプロジェクトを開発してサポートするにつれて、コードのサポートやチームの速度のスケーリングが難しくなる可能性があります。
+  **テストが困難** - コードの行が増えると、コードベースの入力およびエントリポイントの可能なすべての組み合わせをユニットテストすることが難しくなります。一般的に、コードの少ない小規模なサービスに対してユニットテストを実装する方が簡単です。

推奨される代替方法は、モノリシック Lambda 関数を個々のマイクロサービスに分解し、単一の Lambda 関数を単一の明確に定義されたタスクにマッピングすることです。いくつかの API エンドポイントを持つこのシンプルなウェブアプリケーションでは、結果として得られるマイクロサービスベースのアーキテクチャを API Gateway ルートに基づいて作成できます。

![\[イベント駆動型アーキテクチャの図 14\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/event-driven-architectures-figure-14.png)


### Lambda 関数が暴走する原因となる再帰パターン
<a name="recursive-runaway"></a>

AWS サービスは Lambda 関数を呼び出すイベントを生成し、Lambda 関数は AWS サービスにメッセージを送信できます。一般に、Lambda 関数を呼び出すサービスまたはリソースは、関数の出力先のサービスまたはリソースとは異なる必要があります。これを管理しないと、無限ループが発生する可能性があります。

例えば、Lambda 関数が Amazon S3 オブジェクトにオブジェクトを書き込むと、配置イベントを介して同じ Lambda 関数が呼び出されます。この呼び出しにより 2 番目のオブジェクトがバケットに書き込まれ、同じ Lambda 関数が呼び出されます。

![\[イベント駆動型アーキテクチャの図 15\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/event-driven-architectures-figure-15.png)


ほとんどのプログラミング言語で無限ループが発生する可能性がありますが、このアンチパターンはサーバーレスアプリケーションでより多くのリソースを消費する可能性があります。Lambda および Amazon S3 の両方がトラフィックに基づいて自動的にスケールされるため、ループによって Lambda が利用可能なすべての同時実行数を消費するようにスケールする可能性があり、Amazon S3 が引き続きオブジェクトを書き込んで Lambda 用により多くのイベントを生成します。

この例では S3 を使用していますが、再帰ループのリスクは Amazon SNS、Amazon SQS、DynamoDB、その他のサービスにも存在します。[再帰ループ検出](invocation-recursion.md)を使用し、このアンチパターンを見つけて回避できます。

### Lambda 関数を呼び出す Lambda 関数
<a name="functions-calling-functions"></a>

関数を使用すると、カプセル化とコードの再利用が可能になります。ほとんどのプログラミング言語は、コードベース内で関数を同期的に呼び出すコードの概念をサポートしています。この場合、呼び出し元は関数がレスポンスを返すまで待機します。

**注記**  
他の Lambda 関数を直接呼び出す Lambda 関数は、コストと複雑さの懸念から一般的にアンチパターンですが、これは[耐久性のある関数](durable-functions.md)には適用されません。耐久性のある関数は、他の関数を呼び出してマルチステップワークフローをオーケストレーションするように特別に設計されています。

これが従来のサーバーまたは仮想インスタンスで発生すると、オペレーティングシステムスケジューラが使用可能な他の作業に切り替えます。サーバーの所有と運用のための固定コストを支払うため、CPU が 0% で動作している場合も 100% で動作している場合も、アプリケーションの全体的なコストには影響しません。

このモデルは、多くの場合、サーバーレス開発にはうまく適応しません。例えば、注文を処理する 3 つの Lambda 関数で構成されるシンプルな e コマースアプリケーションについて考えてみましょう。

![\[イベント駆動型アーキテクチャの図 16\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/event-driven-architectures-figure-16.png)


この例では、*Create order* 関数が *Process payment* 関数を呼び出し、次にこの関数が *Create invoice* 関数を呼び出します。この同期フローはサーバー上の単一のアプリケーション内では機能する場合もありますが、分散サーバーレスアーキテクチャでは次のようないくつかの回避可能な問題が発生します。
+  **コスト** - Lambda を使用すると、呼び出しの時間に対して課金されます。この例では、図に赤で示されているように、*Create invoice* 関数の実行中に他の 2 つの関数も待機状態で実行されます。
+  **エラー処理** - ネストされた呼び出しでは、エラー処理が大幅に複雑化する可能性があります。例えば、*Create invoice* でエラーが発生した場合、*Process payment* 関数で請求を取り消す必要がある場合も、そうではなく *Create invoice* プロセスを再試行する場合もあります。
+  **密結合** - 支払いの処理は、通常、インボイスの作成よりも時間がかかります。このモデルでは、ワークフロー全体の可用性が最も遅い関数によって制限されます。
+  **スケーリング** - 3 つすべての関数の[同時実行数](lambda-concurrency.md)が等しくなければなりません。これにより、負荷の高いシステムでは、他で必要な数よりも多くの同時実行数が使用されます。

サーバーレスアプリケーションでは、このパターンを回避するための一般的なアプローチが 2 つあります。まず、Lambda 関数間で Amazon SQS キューを使用します。ダウンストリームプロセスがアップストリームプロセスよりも遅い場合、キューがメッセージを永続的に存続させて、2 つの関数を分離します。この例では、*Create order* 関数が Amazon SQS キューにメッセージを発行し、*Process payment* 関数がキューからのメッセージを消費します。

2 つ目の方法は AWS Step Functions を使用することです。複数のタイプの障害と再試行のロジックを持つ複雑なプロセスの場合、ワークフローのオーケストレーションに必要なカスタムコードの量を減らすために Step Functions が役立ちます。これにより、Step Functions が作業をオーケストレーションし、エラーと再試行を堅牢に処理するため、Lambda 関数にはビジネスロジックのみが含まれます。

### 単一の Lambda 関数内での同期待機
<a name="synchronous-waiting"></a>

同時実行の可能性があるアクティビティが単一の Lambda 関数内で同期的にスケジュールされていないことを確認します。例えば、Lambda 関数が S3 バケットに書き込んでから、DynamoDB テーブルに書き込む場合があります。

![\[イベント駆動型アーキテクチャの図 17\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/event-driven-architectures-figure-17.png)


この設計では、アクティビティがシーケンシャルであるため、待機時間が複合化されます。2 番目のタスクが最初のタスクの完了に依存する場合、個別の Lambda 関数を 2 つ持つことによって合計の待機時間および実行コストを削減できます。

![\[イベント駆動型アーキテクチャの図 19\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/event-driven-architectures-figure-19.png)


この設計では、オブジェクトを Amazon S3 バケットに配置した直後に、最初の Lambda 関数が応答します。S3 サービスが 2 番目の Lambda 関数を呼び出し、これにより DynamoDB テーブルにデータが書き込まれます。このアプローチにより、Lambda 関数の実行の合計待機時間が最小限に抑えられます。

# Lambda アプリケーションの設計
<a name="concepts-application-design"></a>

優れた設計のイベント駆動型アプリケーションは、AWS サービスとカスタムコードを組み合わせてリクエストとデータを処理および管理します。この章では、アプリケーション設計における Lambda 固有のトピックに焦点を当てます。サーバーレスアーキテクトは、ビジーな本番稼働システム向けにアプリケーションを設計する際に、多くの重要な考慮事項があります。

ソフトウェア開発と分散システムに適用されるベストプラクティスの多くは、サーバーレスアプリケーション開発にも適用されます。全体的な目標は、以下を備えたワークロードを開発することです。
+  **信頼性** - エンドユーザーに高い可用性のレベルを実現します。AWS サーバーレスサービスは障害にも備えて設計されているため、信頼性があります。
+  **耐久性** - ワークロードの耐久性のニーズを満たすストレージオプションを用意しています。
+  **安全性** - ワークロードへのアクセスを保護して影響範囲を制限するため、ベストプラクティスに従って提供されるツールを使用します。
+  **パフォーマンス** - コンピューティングリソースを効率的に使用し、エンドユーザーのパフォーマンスニーズを満たします。
+  **コスト効率** - 過剰に支出しなくても増加する可能性がある不要なコストを回避し、大きなオーバーヘッドなしで廃止できるアーキテクチャを設計します。

次の設計原則により、これらの目標を達成するためのワークロードを構築できます。すべての原則がすべてのアーキテクチャに適用されるわけではありませんが、一般的なアーキテクチャの決定の参考になります。

**Topics**
+ [

## カスタムコードの代わりのサービスの使用
](#services-custom-code)
+ [

## Lambda 抽象化レベルの概要
](#level-abstraction)
+ [

## 関数にステートレスの実装
](#statelessness-functions)
+ [

## 結合を最小限に抑制
](#minimize-coupling)
+ [

## バッチではなく、オンデマンドデータ向けに構築
](#on-demand-batches)
+ [

## 複雑なワークフローのオーケストレーションオプションを選択する
](#orchestration)
+ [

## べき等性の実装
](#retries-failures)
+ [

## 複数の AWS アカウントを使用してクォータを管理する
](#multiple-accounts)

## カスタムコードの代わりのサービスの使用
<a name="services-custom-code"></a>

サーバーレスアプリケーションは、通常、Lambda 関数で実行されるカスタムコードと統合された複数の AWS サービスで構成されます。Lambda はほとんどの AWS サービスと統合できますが、サーバーレスアプリケーションで最もよく使用されるサービスは次のとおりです。


| Category | AWS のサービス | 
| --- | --- | 
|  コンピューティング  |  AWS Lambda  | 
|  データストレージ  |  Amazon S3 Amazon DynamoDB Amazon RDS  | 
|  API  |  Amazon API Gateway  | 
|  アプリケーション統合  |  Amazon EventBridge Amazon SNS Amazon SQS  | 
|  オーケストレーション  |  Lambda の耐久性のある関数 AWS Step Functions  | 
|  データのストリーミングと分析  |  Amazon Data Firehose  | 

**注記**  
多くのサーバーレスサービスは、DynamoDB や Amazon S3 など、複数のリージョンのレプリケーションとサポートを提供します。Lambda 関数はデプロイパイプラインの一部として複数のリージョンにデプロイでき、API Gateway はこの設定をサポートするように設定できます。これを実現する方法を示す「[アーキテクチャの例](https://d1.awsstatic.com/architecture-diagrams/ArchitectureDiagrams/serverless-architecture-for-global-applications-ra.pdf?did=wp_card&trk=wp_card)」を参照してください。

分散アーキテクチャには、自分で構築したり、AWS サービスを使用して実装したりできる、確立された一般的なパターンが多数あります。ほとんどのお客様にとって、これらのパターンをゼロから開発するために時間を費やすことによる商業的な価値はほとんどありません。アプリケーションがこれらのパターンのいずれかを必要とする場合は、対応する AWS サービスを使用します。


| パターン | AWS のサービス | 
| --- | --- | 
|  [キュー]  |  Amazon SQS  | 
|  イベントバス  |  Amazon EventBridge  | 
|  パブリッシュ/サブスクライブ (ファンアウト)  |  Amazon SNS  | 
|  オーケストレーション  |  Lambda の耐久性のある関数 AWS Step Functions  | 
|  API  |  Amazon API Gateway  | 
|  イベントストリーム  |  Amazon Kinesis  | 

これらのサービスは Lambda と統合するように設計されており、Infrastructure as Code (IaC) を使用してサービス内のリソースを作成および破棄できます。アプリケーションをインストールしたり、サーバーを設定したりすることなく、[AWS SDK](https://aws.amazon.com/tools/) 経由でこれらのサービスを使用できます。Lambda 関数でコードを介してこれらのサービスを使用することに習熟することは、適切に設計されたサーバーレスアプリケーションを作成するための重要なステップです。

## Lambda 抽象化レベルの概要
<a name="level-abstraction"></a>

Lambda サービスは、Lambda 関数を実行する基盤となるオペレーティングシステム、ハイパーバイザー、ハードウェアへのアクセスを制限しています。このサービスは、インフラストラクチャを継続的に改善および変更して機能を追加し、コストを削減し、サービスのパフォーマンスを向上させています。コードでは、Lambda がどのように設計されているかについての知識がなく、ハードウェアのアフィニティがないことを前提とする必要があります。

同様に、Lambda と他のサービスとの統合は AWS によって管理され、少数の設定オプションのみが公開されます。例えば、API Gateway および Lambda が対話すると、負荷分散はサービスによって完全に管理されるため、負荷分散の概念はありません。いつでも関数を呼び出すときにサービスが使用する[アベイラビリティーゾーン](https://aws.amazon.com/about-aws/global-infrastructure/regions_az/)、あるいは Lambda が実行環境をスケールアップまたはスケールダウンする時期を決定する方法について、ユーザーは直接制御することもできません。

この抽象化により、アプリケーションの統合の側面、データのフロー、ワークロードがエンドユーザーに価値を提供するビジネスロジックに集中できるようになります。サービスが基盤となるメカニズムを管理できるようにすることで、お客様が維持するカスタムコードが減り、アプリケーションをより迅速に開発できます。

## 関数にステートレスの実装
<a name="statelessness-functions"></a>

標準の Lambda 関数には、環境は単一の呼び出しのみに対して存在する考える必要があります。関数を最初に起動するとき、必要な状態を初期化する必要があります。例えば、関数が DynamoDB テーブルからデータ取得が必要な場合があります。終了する前に、Amazon S3、DynamoDB、Amazon SQS などの耐久性の高い保存場所に永続的なデータ変更をコミットする必要があります。既存のデータ構造や一時ファイル、あるいは複数の呼び出しによって管理される内部状態に依存してはなりません。

耐久性のある関数を使用すると、状態は呼び出し間に自動的に保持されるため、状態を外部ストレージに手動で保持する必要がなくなります。ただし、DurableContext で明示的に管理されていないデータについては、ステートレスの原則に引き続き従う必要があります。

データベース接続およびライブラリ、あるいはロード状態を初期化するには、[静的初期化](lambda-runtime-environment.md#static-initialization)を活用できます。パフォーマンスを向上させるために実行環境は可能な限り再利用されるため、これらのリソースを初期化するためにかかる時間は複数の呼び出しに分散できます。ただし、関数で使用される変数やデータは、このグローバルスコープ内に保存しないでください。

## 結合を最小限に抑制
<a name="minimize-coupling"></a>

ほとんどのアーキテクチャでは、より少なく、より長い関数よりも、より多く、より短い関数を優先する必要があります。各関数の目的は、ワークフロー全体やトランザクションの量を把握したり期待したりすることなく、関数に渡されたイベントを処理することである必要があります。これにより、関数は他のサービスとの結合が最小限になり、イベントのソースに依存しなくなります。

頻繁に変更されないグローバルスコープ定数は、デプロイなしで更新できるように環境変数として実装する必要があります。シークレットまたは機密情報は、[AWS Systems Manager パラメータストア](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html)または [AWS Secrets Manager](https://aws.amazon.com/secrets-manager/) に保存し、関数によってロードする必要があります。これらのリソースはアカウント固有であるため、複数のアカウントにまたがるビルドパイプラインを作成できます。このパイプラインは、環境ごとに適切なシークレットをロードします。シークレットを開発者に公開したり、コードを変更したりする必要はありません。

## バッチではなく、オンデマンドデータ向けに構築
<a name="on-demand-batches"></a>

多くの従来のシステムは、定期的に実行され、時間の経過と共に蓄積されたトランザクションのバッチを処理するように設計されています。例えば、銀行業務用のアプリケーションが 1 時間ごとに実行され、中央台帳で ATM トランザクションが処理される場合があります。Lambda ベースのアプリケーションでは、カスタム処理はすべてのイベントによってトリガーされる必要があり、必要に応じて同時実行数をスケールアップして、トランザクションをほぼリアルタイムで処理できます。

標準の Lambda 関数の実行時間は 15 分に制限されますが、耐久性のある関数は最大 1 年間実行できるため、長時間の処理ニーズに適しています。ただし、可能な場合は、バッチ処理よりもイベント駆動型処理を引き続き優先する必要があります。

Amazon EventBridge のルールで[スケジュールされた式を使用すると](https://docs.aws.amazon.com/eventbridge/latest/userguide/scheduled-events.html)、サーバーレスアプリケーションで [cron](https://en.wikipedia.org/wiki/Cron) タスクを実行できますが、これは控えめに使用するか、最後の手段として使用する必要があります。バッチを処理するスケジュールされたタスクでは、トランザクションの量が 15 分間の Lambda 時間制限内で処理できる量を超える可能性があります。外部システムの制限によりスケジューラを使用しなくてはならない場合は、通常、最短の妥当な繰り返し期間をスケジュールする必要があります。

例えば、Lambda 関数をトリガーするバッチプロセスを使用して、新しい Amazon S3 オブジェクトのリストを取得することはベストプラクティスではありません。これは、サービスが、15 分間の Lambda 関数内で処理できる数よりも多くの新しいオブジェクトをバッチ間で受け取る可能性があるためです。

![\[イベント駆動型アーキテクチャの図 10\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/event-driven-architectures-figure-10.png)


代わりに、新しいオブジェクトがバケットに配置されるたびに、Amazon S3 によって Lambda 関数が呼び出される必要があります。このアプローチは大幅にスケーラブルであり、ほぼリアルタイムで処理されます。

![\[イベント駆動型アーキテクチャの図 11\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/event-driven-architectures-figure-11.png)


## 複雑なワークフローのオーケストレーションオプションを選択する
<a name="orchestration"></a>

分岐ロジック、障害モデルのさまざまなタイプ、再試行ロジックを含むワークフローは、通常はオーケストレーターを使用して全体的な実行の状態を管理します。標準の Lambda 関数でアドホックオーケストレーションを構築しないでください。これにより、密結合で複雑なルーティングコードになり、自動状態復旧ができなくなります。

代わりに、次のいずれかの専用オーケストレーションオプションを使用します。
+ **[Lambda の耐久性のある関数](durable-functions.md):** 自動チェックポイント設定、組み込まれた再試行、および実行リカバリを備えた標準プログラミング言語を使用したアプリケーション中心のオーケストレーション。Lambda 内のビジネスロジックとともにコードにワークフローロジックを保持したいデベロッパーに最適です。
+ **[AWS Step Functions](with-step-functions.md):** 220 以上の AWS サービスへのネイティブ統合によるビジュアルワークフローオーケストレーション。マルチサービスの調整、メンテナンス不要のインフラストラクチャ、ビジュアルワークフロー設計に最適です。

これらのオプションの選択に関するガイダンスについては、「[耐久性のある関数か Step Functions か](durable-step-functions.md)」を参照してください。

[ Step Functions](https://aws.amazon.com/step-functions/) では、ステートマシンを使用してオーケストレーションを管理します。これにより、コードからエラー処理、ルーティング、分岐ロジックが抽出され、JSON を使用して宣言されたステートマシンに置き換えられます。ワークフローをより堅牢でオブザーバビリティにするだけでなく、ワークフローにバージョニングを追加し、ステートマシンをコードリポジトリに追加できるコード化されたリソースにすることもできます。

Lambda 関数のより簡単なワークフローが時間の経過とともに複雑化することは一般的です。本番稼働サーバーレスアプリケーションを運用する場合、このロジックをステートマシンまたは耐久性のある関数に移行できるように、この状況がいつ発生しているかを特定することが重要です。

## べき等性の実装
<a name="retries-failures"></a>

Lambda を含む AWS サーバーレスサービスには耐障害性があり、障害を処理するように設計されています。例えば、サービスが Lambda 関数を呼び出してサービス中断が発生した場合、Lambda は別のアベイラビリティーゾーンで関数を呼び出します。関数がエラーをスローした場合、Lambda は呼び出しを再試行します。

同じイベントが複数回受信される可能性があるため、関数は[べき等性](https://en.wikipedia.org/wiki/Idempotence)を持つように設計する必要があります。これは、同じイベントを複数回受信しても、イベントが最初に受信されたときと結果が変化しないことを意味します。

DynamoDB テーブルを使用して最近処理された識別子を追跡し、トランザクションが以前に既に処理されたかどうかを判断することにより、Lambda 関数にべき等性を実装できます。DynamoDB テーブルは、通常、[有効期限 (TTL)](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/TTL.html) 値を実装し、項目を期限切れにすることで、使用されるストレージ領域を制限します。

## 複数の AWS アカウントを使用してクォータを管理する
<a name="multiple-accounts"></a>

AWS の多くの [Service Quotas](gettingstarted-limits.md) は、アカウントレベルで設定されます。ワークロードをさらに追加すると、制限を短時間で使い果たす可能性があることを意味します。

この問題を解決する効果的な方法は、複数の AWS アカウントを使用して各ワークロードをそれぞれのアカウント専用にすることです。これにより、クォータが他のワークロードや非本番稼働用リソースと共有されるのを防ぎます。

 さらに、[AWS 組織](https://aws.amazon.com/organizations/)を使用することにより、これらのアカウントの請求、コンプライアンス、セキュリティを一元的に管理できます。ポリシーをアカウントのグループにアタッチすると、カスタムスクリプトや手動プロセスを回避できます。

1 つの一般的なアプローチは、開発者それぞれに AWS アカウントを提供し、ベータデプロイステージと本番稼働用に個別のアカウントを使用する方法です。

![\[アプリケーション設計の図 3\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/application-design-figure-3.png)


このモデルでは、開発者はそれぞれアカウントに対して独自一連の制限があるため、その使用状況はお使いの本番稼働環境には影響しません。このアプローチにより、開発者は開発マシンに Lambda 関数を、個々のアカウントのライブクラウドリソースに対してローカルでテストできます。