Provisioned Concurrency for Lambda Functions  ちょっと試してみた。

AWSの一番好きなサービスはAWS Lambda な人です。

--- 

re:invnet 2019真っ最中で、量子コンピューティングサービス出てきたり、EKS for Fargateとか出ている中で、Lambdaのアップデートがいくつかありました。
その中で、過去の経緯上、個人にちょっと熱かった
[Provisioned Concurrency for Lambda Functions](https://aws.amazon.com/jp/blogs/news/new-provisioned-concurrency-for-lambda-functions/)
についてやってみたので、所感のメモです。

例によって、クラスメソッドさんが速報を上げてくれているので、こちらも

[[速報]コールドスタート対策のLambda定期実行とサヨナラ！！ LambdaにProvisioned concurrencyの設定が追加されました　 #reinvent | Developers.IO](https://dev.classmethod.jp/cloud/aws/lambda-support-provisioned-concurrency/)


### Lambdaをポーリング

AWS Lambda、非常に便利なんですが、VPC内で使うと、実行時にENI作成が起きて、場合によっては、１分ぐらいかかることがあって、
API Gatewayから呼び出したりすると、API Gatewayが先にタイムアウトする(最大29秒なので)ってことが起きていました。

今年、ENIをLambda関数デプロイ時に作成し、起動を高速化する[改善](https://aws.amazon.com/jp/blogs/compute/announcing-improved-vpc-networking-for-aws-lambda-functions/)がありましたが、それでも、リクエストが増えたときには、Lambdaの起動が発生し、コールドスタートは発生するっていう状況でした。

コールドスタートをなるべく少なくするために、Lambdaを起動し続けるように、ポーリングするという手段が取られていたわけですが、
今日発表された**Provisioned Concurrency for Lambda Functions**で、自前でポーリングをしなくても良いようになったようです。

あ、コールドスタートについては、Lambda関数のモジュールの大きさとかも絡んでくるので、一概に遅いわけではないです。悪しからず。

### 試してみた
すでに、東京リージョンにもできているので、新規作成してやってみます。

新規作成して、VPC指定（別に指定する必要はないみたいですけど、まあ）、バージョンを作成します。

同時実行数という項目の中に、***プロビジョニングされた同時実行***とい項目が追加されています。
<img width="1496" alt="設定画面" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72752/548112aa-d45d-8140-28be-661c41538b2a.png">

追加ボタンを押すとこんな感じのダイアログが出てきます。
<img width="855" alt="登録ダイアログ" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72752/4c6e15be-e925-13aa-e0fb-0ef79f2f3bbd.png">
ちなみに、バージョン/エイリアス指定だと、当たり前ですが、選択肢が減ります。
<img width="848" alt="バージョンで選択した場合" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72752/840e9da1-d063-3840-7950-260fa557d621.png">

なお、#latestは指定できないみたいです。
<img width="601" alt="latest指定不可" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72752/404e0a0d-fc00-b2ac-9f83-beb4e2cad37c.png">

で設定してみます。とりあえず *プロビジョニングされた同時実行* は１０にしてみました
<img width="831" alt="設定状況" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72752/8962ef3f-3272-5e61-9366-053fff10389d.png">

実行数は、予約済み実行数と一緒で、「アカウントで指定されているLambdaの同時実行数から、一定数を割り当てる」ので、
あまり割り当てすぎると、割り当てしてないLambdaに大量アクセスがあった場合にスロットリングエラーが起きるかもしないですね。
今回は適当に10割り当てましたが、ちゃんとアクセス数の検討、負荷試験を実施して、適切な数値をセットしたいですね。

保存を押すと、設定が始まります。
<img width="1464" alt="設定中" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72752/1ba09161-76ec-a536-a10a-026b3f8c3b52.png">

なお。この状態では、該当Lambdaのロググループ内は空ですが、
<img width="1091" alt="スクリーンショット 2019-12-04 13.36.09.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72752/12ab6ba8-5fb2-a34d-ac3e-8d411efd2e9e.png">

設定が進むと、ログストリームができてきます。（つまりLambdaのコンテナが起動した状態）
<img width="847" alt="設定中" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72752/5c29f289-f7c2-df4e-8792-f6e83f7d2841.png">

完了すると、、、**なぜか20個のログストリームができていました。謎です。** この事象については何か分かったら追記します。。。
<img width="871" alt="設定完了済み？" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72752/cbe0dff8-7b7a-f9b2-f44c-26ebf0a3452b.png">

ちなみに、ログストリームには何も書かれてないです。テンプレートそのままなので、起動時に実行される処理があって、ログに吐き出すようにしていれば、そちらの記載されるのではないかと。

<img width="1093" alt="ログストリームの中は空" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72752/4e7a3edb-e7ca-9b5c-057c-a3340aced733.png">

で、試しに、設定したバージョンでアクセス（テスト実行してます）すると、
<img width="1437" alt="テスト実行" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72752/b87be28d-13e7-06b0-d1a1-c749fc73abcd.png">

起動したうちの1つにイベントに記載されました。
<img width="1338" alt="イベント" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72752/88bf006b-0927-da6e-3750-e86007c266eb.png">

なお、#latestでテスト実行すると、
<img width="1420" alt="latestでテスト実行" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72752/9d9cf989-570f-d702-d3b4-a2d80a3f833f.png">

対象外なので、別のログストリームが作成されます。
<img width="1331" alt="別のログストリーム作成" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72752/5bdbb0a5-3ac0-49fb-862c-26d2d5bab5d4.png">

とりあえずは今日のところは以上です。
公式のブログにある通り、Apache Benchなどで、負荷かけてみないとダメかなーというところは、ちょっと今後の課題ということで。

### 価格

課金に関しては、以下になっているようです。

|| Price |
|:-----------------:|:------------------:|
| Provisioned Concurrency | $0.000005384 for every GB-second |
| Requests | $0.20 per 1M requests |
| Duration | $0.000012562 for every GB-second |

以下めっちゃGoogle翻訳ですがw、
プロビジョニングされた同時実行性（Provisioned Concurrency）は、機能で有効化してから無効化するまでの時間から計算され、最も近い5分に切り上げられます。価格は、関数に割り当てるメモリの量と、それに設定する同時実行の量によって異なります。

期間(Duration)は、コードが実行を開始してから戻るか終了するまでの時間から計算され、最も近い100ミリ秒に切り上げられます。価格は、関数に割り当てるメモリの量によって異なります。

**Lambdaの無料利用枠は、Provisioned Concurrencyが有効になっている機能には適用されません。関数のプロビジョニングされた同時実行を有効にして実行すると、以下の価格に基づいてリクエストと期間に対して課金されます。**

無料利用枠対象外になるんですねー。これは注意が必要かも。

---

ポーリングを自前で設定しなくてもよくなったのは、大きいかもしれません。
数が多くなると、設定も面倒ですからねぇ。。。（遠い目）
こっちも一緒か。。。

ちなみに、同時に、[Using Amazon RDS Proxy with AWS Lambda | Amazon Web Services](https://aws.amazon.com/jp/blogs/compute/using-amazon-rds-proxy-with-aws-lambda/)
というアップデートも発表されており、
今年あったLambdaのアップデートで、今まで結構アンチパターンだと言われていた、Lambda + RDSの組み合わせが使いやすくなったのではないでしょうか？

---

**2019/12/6 追記**
作って1日放置してるんですが、 Cloudwatch Logsのロググループを見る限り、定期的にコンテナが再作成されている感じがします。
Pollingでもどんなにアクセスしてても、定期的には再作成されるような挙動だったので、この辺は一緒かもしれません。

そして、Billingのところでは、Provisioned Concurrency用の項目が出現。
<img width="1429" alt="billing" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72752/8436e2f4-1267-3a0d-5956-5e9a5169139f.png">

ほほ、Lambdaで課金されてるーwって軽く盛り上がった人ですw
個人の検証用アカウントなのでLambdaの無料枠になることはまずないので。。。

---

随時更新します。