VPC LambdaとRDS Proxyはサーバーレスの常識を変えるのか。検証しました!
最近はコンテナオーケストレーションに興味が偏っているやっさんでございます。
弊社ではサーバーレスを積極的に活用しておりまして、
Lambda SDPに認定されております。
本記事では、VPC LambdaとRDS Proxyはサーバーレスの常識を変えるのかを検証しました。
VPC Lambdaの起動速度を検証
VPC Lambdaは2019年9月に東京リージョンで起動速度が改善されました。
Lambda関数が最初に作成された時、Hyperplane ENIを作成するようになります。
VPC Lambdaの起動速度を測ってみます。
Heyという負荷試験ツールで200リクエストを実行します。
結果を見ていただくと分かります通り、レイテンシは大きく改善されています。
Summary:
Total: 1.2073 secs
Slowest: 0.9351 secs
Fastest: 0.0392 secs
Average: 0.2379 secs
Requests/sec: 165.6654
Total data: 9059 bytes
Size/request: 45 bytes
Response time histogram:
0.039 [1] |
0.129 [135] |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
0.218 [9] |■■■
0.308 [5] |■
0.398 [0] |
0.487 [0] |
0.577 [0] |
0.666 [15] |■■■■
0.756 [26] |■■■■■■■■
0.846 [6] |■■
0.935 [3] |■
同時実行数を見てみます。
CloudWatch メトリクスの ConcurrentExecutions
を確認します。
26の同時実行数を確認できました。
コールドスタートの速度も測ってみます。
CloudWatch Logs Insightで以下のクエリを実行します。
filter @type = "REPORT" and @initDuration > 0
| stats avg(@initDuration) as init_dur_avg, max(@initDuration) as init_dur_max , min(@initDuration) as init_dur_min
平均76msecはとても速いですね。素晴らしい結果が出ました。
これだけ見るとVPC Lambdaは本番のワークロードでも活用できそうに思えますが ...
2秒 ~ 6秒のレイテンシが発生する。何が起きているのか
何度か実行していると以下のように、レイテンシ増加のケースがありました。
何が起きているのでしょうか。
Summary:
Total: 2.7564 secs
Slowest: 2.0630 secs
Fastest: 0.0792 secs
Average: 0.5095 secs
Requests/sec: 72.5585
Total data: 10975 bytes
Size/request: 54 bytes
Response time histogram:
0.079 [1] |
0.278 [139] |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
0.476 [0] |
0.674 [5] |■
0.873 [4] |■
1.071 [1] |
1.269 [0] |
1.468 [29] |■■■■■■■■
1.666 [16] |■■■■■
1.865 [3] |■
2.063 [2] |■
確認したところ、レイテンシが増加するケースにおいて
追加のENIが作成されていることが分かりました。
つまるところ、ENI作成によるレイテンシを許容できない場合においては
VPC Lambdaを本番のワークロードで利用するべきではないと考えます。
これは今後改善されるのでしょうか。期待したいところです。
RDS Proxy
次にRDS Proxyを試します。
スケールしたLambdaの実行はそれぞれ独立していて、
RDSへのコネクションをプールすることは難しく、
アンチパターンとされていました。
RDS Proxyによりコネクションが一定数確保され、使い回すことができるようになります。
接続プールの最大接続数について
RDS Proxyの重要な設定項目として、
ターゲットグループの 接続プールの最大接続数
があります。
Lambdaは同時実行数が増加すれば、その数だけコネクションが発生します。
なお、RDSの最大コネクション数はインスタンスタイプによって異なります。
もちろん、この最大コネクション数を変更することは可能ですが、
小さいインスタンスタイプに対して最大コネクション数を増やした場合、メモリ枯渇などRDS側の問題が発生します。
ですので、Lambdaの本番ワークロードの同時実行数を定め、
同時実行数に適したRDSのインスタンスタイプを選択し、
コネクション数をRDS Proxyで確保する必要があります。
RDS Proxyを利用した場合においても、最大接続数を超えた接続要求がある場合、
Lambdaはコネクションの解放を待つことになり、
レイテンシ増加を引き起こします。
RDS Proxyは料金が発生する
RDS Proxyは利用料金が発生します。
2020年4月時点の料金は以下となっています。
基となるデータベースインスタンスの vCPU あたりの料金: 0.018USD/時間
m5.large、1,440 vCPU 時間 (2 vCPU x 24 時間 x 30 日) の場合は25.92USDの料金が発生します。
スペックの高いインスタンスタイプを利用している場合は、決して無視できない金額になるでしょう。
RDS Proxyの検証
RDS Proxyを検証していきます。
Heyで200リクエストを実行しコネクション数の増加を確認しました。
コネクション超過エラーとはならず捌けていることが確認できます。
しかし、ここで思わぬ問題に遭遇しました。
いくつかのLambdaでエラーが発生しているのです。
Status code distribution:
[200] 71 responses
[502] 39 responses
golangで検証していたのですが、
この問題につまづき、Pythonでも検証を進めました。
しかしながら、Pythonでも同様のエラーが発生します。
エラー内容としては、DBに接続できない旨のエラーが出力されていました。
→ Amazon RDS ProxyがGAとなり、DBに接続できないエラーは解消されました!
出力されたエラー内容
mysql.connector.errors.ProgrammingError: 1045 (28000): Access denied for user 'root'@'%' (using password: YES)
RDS Proxyを利用しない場合はエラーは発生しない
PythonでRDS Proxyを利用せずに検証した結果が以下の通りです。
エラーなくすべて捌けています。
Summary:
Total: 3.6572 secs
Slowest: 2.2241 secs
Fastest: 0.1054 secs
Average: 0.8839 secs
Requests/sec: 54.6862
Total data: 1000 bytes
Size/request: 5 bytes
Response time histogram:
0.105 [1] |
0.317 [4] |■■
0.529 [105] |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
0.741 [41] |■■■■■■■■■■■■■■■■
0.953 [0] |
1.165 [0] |
1.377 [0] |
1.589 [1] |
1.800 [1] |
2.012 [5] |■■
2.224 [42] |■■■■■■■■■■■■■■■■
Latency distribution:
10% in 0.4624 secs
25% in 0.4930 secs
50% in 0.5254 secs
75% in 0.6284 secs
90% in 2.1326 secs
95% in 2.1370 secs
99% in 2.1884 secs
Details (average, fastest, slowest):
DNS+dialup: 0.1087 secs, 0.1054 secs, 2.2241 secs
DNS-lookup: 0.0942 secs, 0.0000 secs, 0.3778 secs
req write: 0.0001 secs, 0.0000 secs, 0.0010 secs
resp wait: 0.7748 secs, 0.1052 secs, 1.7916 secs
resp read: 0.0001 secs, 0.0000 secs, 0.0002 secs
Status code distribution:
[200] 200 responses
コネクション数は限界近くまで達しました。
それでもPythonはDBクローズが速いのか、捌けました。
2020年4月時点で、RDS Proxyはプレビュー版となっており、
それゆえに動作が安定しないと思いたいですね。
GAした時にもう一度検証したいと思います。
→ Amazon RDS ProxyがGAとなり、DBに接続できないエラーは解消されました!
Provisioned Concurrencyの考察
Lambdaにおいて見逃せないアップデートとして、
Provisiond Concurrensyがございます。
こちらについて考察します。
料金について
プロビジョニングされた同時実行は個別の料金が発生します。
リクエストと実行時間とは別に 1 GB-秒あたり 0.0000053835USD
の料金が請求されます。
さらに言いますと、 Lambda の無料利用枠は、Provisioned Concurrency が有効になっている関数には適用されません。
前述したように、Lamdaの同時実行数はスケールします。
あくまで個人的な意見ですが、Lambdaの無料利用枠を捨ててまで、
Provisioned Concurrencyを適用する本番ワークロードとは、どのようなケースなのでしょうか。
20や30の同時実行数をProvisioned Concurrencyで確保するのでしたら、
それはもう、コスト的な観点においてECSやEKSの
Fargateも比較対象になってくるのではないかなと思います。
まとめ
- VPC Lambdaの起動速度は高速になり、本番のワークロードで活用できるようになりました。
- しかしながら、ENIが追加作成される場合にレイテンシが発生することを確認できました。これを許容できるシステムであれば問題ありません。
- Lambdaの想定されるワークロードを定め、RDSのインスタンスサイズとRDS Proxyの最大接続数を決めたいところです。
- RDS Proxyは動作が安定せず、エラーが発生しました。2020年4月時点ではプレビュー版であり、GAで改善することを期待したいです。
- RDS Proxy, Provisiond Concurrensyの料金を確認し、Lambdaであるべきなのか、それともECSやEKSのFargateを選択するのかを決めたいところです。
今回利用したソースコードについて
ソースコードは以下の場所にありますので、よろしければご参照ください。
以上です!