はじめに
先日行われた AWS Summit Tokyo 2017 の「全部教えます!サーバレスアプリのアンチパターンとチューニング」メモです。
「AWS Lmbdaを中心としたサーバレスアプリケーションで発生しがちな問題とその対応策について」のセッションでした。
Lambdaが遅い理由
考えられるポイント
- プログラム
- コンピューティングリソース
- アーキテクチャ
プログラム → 各言語のベストプラクティスに従う
コンピューティングリソース → メモリ設定を行うメモリサイズと比例して割り当てられるCPUリソースも割り当てられる。つまり、メモリを倍にするとCPUも倍。
Lambda設定の最適値設定方法
メモリを増やした際に処理時間が大きく短くなる場合がある。
その場合は処理時間が短くならなくなったところが最適値と考えてOK。
Lambdaファンクション実行時に起きていること。
- (ENIの作成)
- コンテナの作成
- デプロイパッケージのロード
- デプロイパッケージの展開
- ランタイム起動・初期化
- 関数/メソッドの実行
1〜6を実行するのがコールドスタート。
1〜5は基本的に毎回同じ内容が実行される → 再利用することで省略して効率化(ウォームスタート)。
コールドスタートが起こる条件
利用可能なコンテナがない場合に発生
- 1つもコンテナがない状態
- 利用可能な数以上に同時に処理すべきリクエストが来た
- コード、設定を変更した
安定的にリクエストが来てたらコードや設定を変更しない限りコールドスタートはほとんど発生しない
コールドスタートは回避できるの?
コールドスタートは利用者側でどうにかできる領域ではない。なので基本的に回避はできない。
つまり、コールドスタートを0にすることは難しいため、それが許容できないのであればAWS Lambdaは使うべきでない。
実行を早くするには?
-
*コンピューティングリソースを増やす
→コンピューティングリソースの割り当てを増やすことで初期化処理が早くなる -
*ランタイムを変える
→AWS Lambdaに限らずJVMの起動は遅い、ただし、一度温まるとコンパイル言語の方が速い傾向。 -
パッケージサイズを小さくする
→サイズが大きくなるとコードのロード及びZip展開に時間がかかる(不要なコードは減らす, 依存関係を減らす, 不要なモジュールは含めない(特にJava))
→JavaだとProGuardなどのコード最適化ツールを使って減らすという方法もある。 -
*VPCは必要でない限り使用しない。
→使うのはVPC内のリソースにどうしてもアクセスする必要があるときだけ。
→VPCを有効にしているとコールドスタート時に10秒から30秒程度余計に必要になる。
→同期実行が必要な箇所やコールドスタートを許容できない箇所ではなるべく使わない。
→VPC内のリソースとの通信が必要なのであれば非同期にする。 -
初期化処理をハンドラの外に書くとコールドスタートが遅くなる。
アーキテクチャの問題
- 同期でInvokeすると同時実行数の制限に引っかかって詰まりがち。
- できるだけ非同期でInvokeするのがスケーラビリティの観点ではオススメ。
- Think Parallel:並列処理を行う。
- 1つあたりのイベントを小さくして同時に並列で動かせるようなアーキテクチャにする。
同時実行数
- 関数の平均実行時間:3s/exec
- 同時実行数="同時"に実行されているタイミング
- 秒間リクエスト:10req/sec
- ストリームベースの場合はシャード単位
Limit Increase(上限緩和)について
標準では1000、実績がない状態でいきなり数千とか数万を申請しても通らない。
もし実績がない状態でどうしても緩和したい場合はサポートへ直接相談。
気をつけよう
- Lambda + RDBMS → Amazon DynamoDBを使う方が良いのでは?
- IP固定したがり問題 → 署名や証明書などで担保すべき。
- サーバレスであれば全く運用が必要ない、インフラ費用が10分の1になる → サーバの管理は不要だが運用は必要。
- Serverless != Monitorless
Lambda使う際の注意
ちゃんとエラー検知などは入れましょう。
- CloudWathcのメトリクス、Errors,Throttles
- CloudWatchのカスタムメトリクス
おわりに
セッションの講演資料がちゃんと共有されているので詳しく知りたい方はそちらを参照願います。
- 全部教えます!サーバレスアプリのアンチパターンとチューニング(Spearker Deck)
関連書籍
「実践AWS Lambda」はセッション登壇者の西谷さんが書かれた本です。