何が起きたのか
作成していたアプリではサーバレス構成にてLambdaからRDS(MySQL)を呼び出していました。
リクエストが増えるとRDSのコネクション数が増加して
すぐにDBコネクションエラーになってしまいました。
最大コネクションの上限値
結論から言うとLambdaとRDS(MySQL)は相性が良くないです。
理由はLambdaからRDSのDBコネクションを貼ると
リクエスト単位でコネクションを張ってしまうため
仕組み上、同時接続に耐えられません
(RDSのコネクション上限数が少ない)
さらにVPC設定すると・・・
セキュリティのため、RDSをLambdaからのみアクセスさせるためには
LambdaとRDSを両方とも
VPC領域に置く必要があるのですが、Lambdaの起動が遅くなる場合があります。
これは、一定時間Lambdaがコールしない場合にスリープ状態になり、
起動する際にENIを生成するのに時間がかかっているのが原因だと考えられます
(どちらかというとLambdaの問題ですが)
詳細は下記参考にしてください
Lambda + API Gateway で処理の実行がむちゃくちゃ遅くなるケースを調べた
この現象の対策としてはLambdaをCloudWatchのイベントにて定期的にキックすることで回避することができます。
対策
結果論から言うとそもそもRDSだとスケールアップの費用対効果が薄いので
DynamoDBの構成にすべきでした。
パフォーマンス比較 | 接続数 | 月額料金(MySQL) | メモリ |
---|---|---|---|
t2.micro | 40コネクションが限界 秒間平均0.666リクエストが上限 |
$12.24 | 1GB |
t2.micro x 2 (read raplica) | マスター:40コネクションが限界 秒間平均0.666リクエストが上限 リードレプリカ:30コネクションが限界 秒間平均0.5リクエストが上限 |
$24.48 | 1GB x 2 |
t2.small | 70コネクションが限界 秒間平均1.1666リクエストが上限 |
$24.48 | 2GB |
t2.medium | 150コネクションが限界 秒間平均1.1666リクエストが上限 |
$48.96 | 4GB |
対策:
①RDSをスケーリング(費用かかる)
②RDSにかかる負荷を減らす
- タイムアウト設定を短くする、処理終了時にLambda側から接続をcloseする
- APIを1つにまとめてリクエスト(コネクション)を減らす(APIの改修、クライアントの改修が必要)
- リクエストをキャッシュする
③DynamoDB乗せ代え(テーブル構造含め、サーバ側の改修が必要、要件満たせるか検討が必要)
暫定対応は①、②ですが、恒久的には③でないと厳しいです。
ただし、DynamoDBはオートスケールはしてくれるもののテーブル構成が制限され、検索機能も貧弱なため専用の設計が必要です。