AWSによるサーバーレスアーキテクチャ - AWS Lambda概要

# 概要

AWS Lambda の勉強を始めようと「[AWSによるサーバーレスアーキテクチャ](https://amzn.to/2tYOWcg "AWSによるサーバーレスアーキテクチャ")」を購入
少し読んでみると非常に良い本なので書籍紹介と自身のLambda備忘録のために投稿
Lambdaについての概要、使い方、制限、注意事項などまとめていく予定

## 紹介書籍

[AWSによるサーバーレスアーキテクチャ](https://amzn.to/2tYOWcg "AWSによるサーバーレスアーキテクチャ")
<a target="_blank"  href="https://www.amazon.co.jp/gp/product/4798155160/ref=as_li_tl?ie=UTF8&camp=247&creative=1211&creativeASIN=4798155160&linkCode=as2&tag=aws_lambda_001-22&linkId=14119ca610f2747cc3038f863971fa17"><img border="0" src="//ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&MarketPlace=JP&ASIN=4798155160&ServiceVersion=20070822&ID=AsinImage&WS=1&Format=_SL110_&tag=aws_lambda_001-22" ></a><img src="//ir-jp.amazon-adsystem.com/e/ir?t=aws_lambda_001-22&l=am2&o=9&a=4798155160" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />

## サーバーレスアーキテクチャの原則

* オンデマンドでコードを実行するために、（サーバーではなく）コンピューティングサービスを使う
* 目的が１つでステートレスな関数を書く
* プッシュベースのイベント駆動パイプラインを設計する
* より厚く、より強力なフロントエンドを作る
* サードパーティサービスを活用する

## サーバーレスの長所と短所

### 長所

* サーバー管理不用
* 低コスト
* 市場投入までの時間短縮
* 実装がシンプル、コード量減る可能性がある
* ☆マルチスレッドを考慮する必要がない
* スケーラブルで柔軟、並列処理が得意

### 短所

* レイテンシーに厳しい制約のあるAPには向かない
* ベンダーロックイン
* パブリッククラウドが提供できる水準よりも高いパフォーマンス、信頼性が求めらえるミッションクリティカルサービスに向かない
* サービス分散化による、リモート呼び出し、ネットワーク越しのエラー処理、レイテンシーの増加
* OSのカスタマイズやその下のインスタンスの調整はできない
* Lambda特有の処理（複数回実行される等）が発生することがある

## Lambda呼び出し方法

* イベント駆動型(非同期型)
 * プッシュモデル
 * プルモデル
* 要求／応答型(同期型)

## 〇Lambda関数実行までの流れ（※１）

1. ENIの作成
2. コンテナの作成
3. デプロイパッケージのロード
4. デプロイパッケージの展開
5. ランタイム起動・初期化
6. 関数/メソッドの実行

* 1.ENIの作成はVPCを利用する場合だけ
* すべてを実行するのがコールドスタート／6.だけ実行するのがウォームスタート

## Lambda関数の状態

* コールド状態：関数のコードがロードされておらず、初期化、セットアップコードがこれから実行される状態
* ウォーム状態：一度以上関数が実行されており関数のコードがロードされている状態

## (処理起動時間がかかる)コールド状態を減らすための施策

* 関数をウォーム状態に保つためにスケジュールイベントを使って定期的に実行するようにする
* 初期化、セットアップコードをイベントハンドラの外に出す。コンテナがウォーム状態なら、そのコードは実行されない
* Lambda関数に割り当てられるメモリの容量を増やす。CPUのシェアは、関数に割り当てられたメモリ容量に応じて決まる
* コードのサイズをできる限り小さくする。不要なモジュールを減らし、インポートのためのrequires()の呼び出しも減らす。インクルードおよび初期化するモジュールを減らせば、起動時のパフォーマンスを上げることができる
* 別の言語も検討してみる。（将来変わるかもしれないが）コールドスタートが最も長いのはJava
* 「新機能 – Lambda 関数のプロビジョニングされた同時実行性」を使用してみる
    * https://aws.amazon.com/jp/blogs/news/new-provisioned-concurrency-for-lambda-functions/
    * [AWS LambdaのJavaは遅い？](https://qiita.com/moritalous/items/632333088948aad7f8c9 "AWS LambdaのJavaは遅い？")

## Lambdaの制限

* 一時ディスク:512MB
* ファイルディスクリプタの数:1024
* プロセスとスレッドの数:1024
* リクエストあたりの処理時間:300秒
* 呼び出し時のリクエスト本体のペイロードサイズ(要求／応答型):6MB
* 呼び出し時のリクエスト本体のペイロードサイズ(イベント駆動型):128KB
* 呼び出し時のレスポンス本体のペイロードサイズ(要求／応答型):6MB

AWS ドキュメント 
[AWS Lambda の制限](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/limits.html "AWS Lambda の制限")

## SDKによるLambda関数直接呼び出しの注意事項

* ユーザーがSDKの一部をダウンロードしなければならない
* Lambda関数の呼び出し方法を変える場合は、クライアント／Lambda関数両方に修正が入る可能性がある
* 悪意のあるユーザーがクライアントプログラムを変更することで、Lambda関数を不正に呼び出すことができてしまう
* HTTP(s)を使った統一的なRESTインターフェイスにならない

## Amazon API Gatewayとの連携

### Lambdaプロキシ統合について

* Lambda統合プロキシ有効：すべてのリクエスト（クエリ文字列、ヘッダー、ステージ変数、パス変数、リクエストコンテキスト、リクエスト本体）をJSONに変換し、イベントオブジェクトとしてLambdaに渡す
* Lambda統合プロキシ無効：統合Request(Response)セクションでマッピングテンプレートを作って、HTTPリクエストをどのようにJSONにマッピングするか定義する必要がある
 * リクエスト本体のペイロードは無効の状態でもマッピングされる
 * 例えば、HTTPヘッダの Authorization をLambdaのeventオブジェクト変数(authTokenという名前とする)にマッピングする場合は以下のように定義する

```json
{
    "authToken" : "$input.params('Authorization')"
}
```

※$inputは、API Gateway上の変数。詳細は以下のリファレンスを参照

[API Gateway のマッピングテンプレートリファレンス](https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html#input-variable-reference "API Gateway のマッピングテンプレートリファレンス")

* ☆統合プロキシを使って、API Gateway(XML)をLambda(JSON)にマッピング変換することはできない
 * 統合プロキシを使ってXMLをそのままRAWデータとしてLambdaに送ってLambdaで解析することは可能
 * その場合、以下のようにマッピング定義をする

```json
{
    "body" : $input.json('$')
}
```

参考URL

[Using API Gateway to pass non-JSON data (e.g. XML) to a Lambda ](https://forums.aws.amazon.com/thread.jspa?messageID=694601 "Using API Gateway to pass non-JSON data (e.g. XML) to a Lambda ")

* Amazon API Gateway での統合タイムアウトのカスタマイズ
    * タイムアウト値は 50 ミリ秒〜29 秒の間で設定可能
    * https://aws.amazon.com/jp/about-aws/whats-new/2017/11/customize-integration-timeouts-in-amazon-api-gateway/

## LambdaとRDSのコネクション数問題について

* 負荷に合わせて異なるサーバーリソースで拡張していくサーバーレスの特徴から長年？制限とされていたLambdaとRDSのコネクション数増加問題についてAWS側で新しい機能がリリースされた（Amazon RDS Proxy）
* [AWS LambdaでAmazon RDS Proxyを使用する](https://aws.amazon.com/jp/blogs/news/using-amazon-rds-proxy-with-aws-lambda/ "AWS LambdaでAmazon RDS Proxyを使用する")

## 補足

☆印は自身の見解として追加
〇印は他の資料からの参照

## 参照

※１:[全部教えます！サーバレスアプリのアンチパターンとチューニング](https://d0.awsstatic.com/events/jp/2017/summit/devday/D4T7-2.pdf "全部教えます！サーバレスアプリのアンチパターンとチューニング")

### 参考ページ

[知っておいたほうがいいLambda関数の呼び出しタイプとリトライ方式まとめ](https://dev.classmethod.jp/cloud/aws/lambda-idempotency/ "知っておいたほうがいいLambda関数の呼び出しタイプとリトライ方式まとめ")