

# 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)
```

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

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