AWS Lambdaの基本概念まとめ


## Lambdaとは
LambdaはAWSが提供するサーバーレスコンピューティングサービス。

サーバレスとはサーバーが不要だったり、存在しないことではなく、利用者がサーバーの構築や管理・運営をしなくていい等のことを指す。

そのため利用者はサーバーの運営や管理をせず、開発に集中することができる。

また、Lambdaはトラフィックに応じて自動でスケーリングしてくれるほかデフォルトでマルチAZで運用されているため、高い可用性を担保することができる。

## 料金体系

Lambdaの料金は、関数の実行時間と実行回数に応じて課金される。
そのため実行されていないときには全く費用が発生しない。

https://docs.aws.amazon.com/ja_jp/whitepapers/latest/how-aws-pricing-works/aws-lambda.html

## 制限

しかしながら、Lambdaには以下のような制限がありすべてのサーバーをLambdaで置き換えることはできない。

- ステートレスである
  - 実行が終わると破棄されるため前回の状態を保持することができない
- 最大実行時間が15分であること
- 同時実行数に制限がある
  - 1リージョンあたり1000

これらの制限からLambda関数は**必要に応じて短い実行時間で実行されるような処理**に向いている。

## Lambdaを使うことのメリット
上記の制限を踏まえた上で、Lambdaのメリットは以下の通り。

- サーバーの構築や運用・管理をしなくてよい
- 必要に応じてコストが発生する
- 自動スケーリングやマルチAZで運用されているため高い可用性を担保することができる

## Lambdaの基本概念
Lambdaを使う上で重要な概念は以下の通り。

### トリガー
トリガーとは**Lambda関数を呼び出すためのきっかけ**を指す。
例えば、以下のような状況でLambda関数を呼び出すことができる。
- S3バケット上にオブジェクトが作成・削除された時
- SNSのトピックにメッセージが送信された時
- CloudWatchでメトリクスがしきい値を超えた時
- API GatewayでAPIが呼び出された時
- CloudWatch Logsでログが出力された時
- CloudWatch Eventでイベントが発生した時
- スケジュール実行でLambda関数を呼び出すように設定

### イベント
イベントとは**AWSリソースの状態の変更やアクションの発生**を指す。
例えば、以下のような状況がイベントになります。
- S3にオブジェクトが作成・削除された時
- CloudWatchでメトリクスがしきい値を超えた時

Lambda関数にはイベントの情報はJSON形式で渡される。
JSONの中にどのような情報が含まれるかはトリガーとなるリソースによって異なり、詳細はトリガーとなるリソースのドキュメントに載っている。
例えば、S3の場合には[こちら](https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/notification-content-structure.html)を参照。

### 実行環境
トリガーとなるイベントが発生すると、Lambdaランタイムと呼ばれるコンテナが起動し、Lambda関数が読み込まれ実行される。
以下の流れで実行環境が起動する。

- メモリ、ランタイム、構成設定で関数環境が作成される
- 関数コードと依存ライブラリがロードされる
- 初期化コードが実行される
- 関数コードが実行される

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/lambda-runtime-environment.html

また、Lambda関数はコールドスタートとウォームスタートの2種類の起動方法があり、それぞれによって関数の起動時間が異なる。

#### コールドスタート
コールドスタートとは、Lambdaに限らずコンピューターの起動方法を指す用語。
コールドスタートの定義と特徴は以下の通り。

定義
- 完全に電源が入っていない状態から起動すること

特徴
- 記憶装置やOSの初期化作業が必要なため起動時間が長い

Lambda関数の場合、**実行環境が準備されてから関数が実行されるのがコールドスタート**となる。
実行環境が準備されてから関数が実行されるので関数が実行されるまでに時間がかかるという特徴を持つ。

最初にLambda関数が呼び出された場合にはコールドスタートとなるためユーザーの体感では関数が実行されるまでに時間がかかると感じるため注意する必要がある。

#### ウォームスタート
ウォームスタートもコールドスタートと同じくコンピューターの起動方法を指す用語。
ウォームスタートの定義と特徴は以下の通り。

定義
- 電源が入っている状態から起動すること

特徴
- 初期化作業が不要なため起動時間が短い

Lambda関数の場合、**既存の実行環境が再利用されることをウォームスタート**と呼ぶ。
実行環境が再利用されるので関数が実行されるまでの時間がコールドスタートに比べて短い特徴を持つ。

Lambda関数は実行後すぐに実行環境を破棄せず、不定期間実行環境を保持し続けるため同じLambda関数を呼び出した場合にはウォームスタートとなる。
どれくらいの時間、実行環境を保持するかはAWS依存のため開発者で設定することはできない。

**Provisioned Concurrency** という仕組みを使えば、コールドスタートを削減することができるが、その分コストが高くなるため注意する必要がある。

https://aws.amazon.com/jp/blogs/news/operating-lambda-performance-optimization-part-1/

https://aws.amazon.com/jp/blogs/news/operating-lambda-performance-optimization-part-2/

### ランタイム
ランタイムとは、Lambda関数を実行するためのプログラミング言語とそのバージョンを指す。
以下の言語がサポートされている。
- Node.js
- Python
- Java
- Ruby
- .NET
- Go

またカスタムランタイムという仕組みを使えば、サポートされていない言語でLambda関数を実行することができる。

### レイヤー
Lambda関数にはデフォルトで含まれているライブラリがあるが、それ以外のライブラリを使いたい場合には必要に応じてインストールする必要がある。
しかし毎回関数実行時にインストールすると関数の起動時間が長くなってしまう。
そのためレイヤーという仕組みを使い、zipファイルをアップロードすることで関数の起動時間を短縮することができる。
また、複数のLambda関数で共通のライブラリを使いたい場合にもレイヤーを使うことで管理が楽になる。

## Lambda関数の登録・実行に必要な権限
Lambda関数を登録・実行するには３つのポイントで権限が必要となる。

### Lambda関数の登録権限
開発者がLambda関数を作成するには、Lambda関数を作成するために必要な`lambda:CreateFunction`の権限が必須となる。

## Lambda関数の実行権限
実際に開発者のIAMユーザーや、イベントの発生源がLambda関数を呼び出して実行するには`lambda:InvokeFunction`の権限が必要となる。

## Lambda関数の実行ロール
Lambda関数がどのような操作をすることができるかを定義するロール。(Lambda関数の振る舞いを表すロール)
Lambda関数はログをCloudWatch Logsへ出力するため、最低限`logs:PutLogEvents`,`logs:createLogGroup`,`logs:createLogStream`の３つの権限が必要となる。
それ以外にもLambda関数内で他のAWSサービスを操作する場合にはその操作に必要な権限が必要となる。


## 同期呼び出しと非同期呼び出し
イベントが発生してLambda関数が呼び出されるときには、同期呼び出しと非同期呼び出しがある。

### 同期呼び出し
同期呼び出しではLambda関数の実行が終了するまでは呼び出し元に処理結果が返らない。
実行が完了すると戻り値が呼び戻し先に返却される。

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/invocation-sync.html

### 非同期呼び出し
非同期呼び出しでは、同期呼び出しと違いLambda関数の実行結果を待たずに後続の処理を実行することができる。
Lambda関数へ送られたイベントはキューへと格納され、呼び出し元にすぐに成功レスポンスを返す。
Lambda関数はキューからイベントを取り出して処理を行い、Lambda関数でイベントを処理したあとの結果は破棄される（呼び出し元には返却されない）。

非同期呼び出しの特徴は以下の通り。

- 実際にLambda関数が実行されるまでに多少のタイムラグが発生する。
- キューからの取り出しは一つずつではなく、複数取り出されて並列に実行される。
- 実行順序は保証されない。
- 正常な場合でも2回実行されることがあるため、冪等性を担保する必要がある。

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/invocation-async.html

## DLQ(Dead Letter Queue)
DLQとは、Lambda関数の非同期呼び出しにおいてLambda関数が失敗した場合に、そのイベントをSQSへのキューへ格納したりSNSへのトピックへ送信する仕組みを指す。
DLQを設定しないでLambda関数の実行に失敗した場合、そのイベントは破棄される。
DLQを構築しておけば失敗したイベントは破棄されず、エラー処理や通知を受けたりすることが可能になります。

## 参考
https://dev.classmethod.jp/articles/summary-of-aws-lambda-mechanism-and-behavior/#AWS%2520Lambda%25E5%25AE%259F%25E8%25A1%258C%25E7%2592%25B0%25E5%25A2%2583

https://zenn.dev/mi_01_24fu/books/d91d10985a5a1a

https://aws.amazon.com/jp/builders-flash/202308/learn-lambda-function-execution/