RDS Proxyを利用した際のクエリのレイテンシーを計測してみた
CX事業本部@大阪の岩田です。 RDS Proxyを利用することのデメリットとしてトランザクションやクエリのレイテンシー増加が挙げられれます。
Depending on your workload, Amazon RDS Proxy can add an average of 5 milliseconds of network latency to query or transaction response time.
単に クライアント <-> RDS という通信よりも クライアント <-> RDS Proxy <-> RDS という通信の方が遅くなるというのはまあ当たり前の話ですね。上記のよくある質問に記載されているようにレイテンシーは5ms程度とされていますが、実際にどの程度レイテンシーが増加するのか計測してみました。
ちなみに前回のブログとの違いですが、前回のブログはSQLを発行せずに計測しているため、単純にクライアントとエンドポイント間の接続速度の計測となります。今回はRDS Proxy <-> RDS間のラウンドトリップまで含めて分析したいので、簡単なSQLを発行して計測しています。
計測方法と環境
ざっくり以下の手順で計測しました。
- メモリを1792MB割り当てたLambdaからRDS/RDS Proxyに接続
- LambdaからRDS/RDS Proxyに簡単なSQLを発行し、SQL発行直前とSQLのレスポンス受信後の時間をログに出力
- RDS Proxyが事前にRDSとの接続を確立している状態で計測するため、事前準備としてEC2からRDS Proxyに接続&切断しておきRDS Proxyに接続をプールしておく
- LambdaとRDS/RDS Proxyの接続確立はhandler外で実施
- LambdaはProvisioned Concurrencyを使用し、常にウォームスタートで起動するように調整
- Lambdaは連続で100回直列実行し、結果をCloudWatch Logs Insightsで集計
- RDSはシングルAZ構成
- LambdaもシングルAZ構成とし、RDSと同じAZのサブネットを設定
- RDS ProxyはシングルAZ構成が取れないため、マルチAZ構成
環境
RDSは以下の設定を利用しました
- バージョン:PostgreSQL 11.8-R1
- インスタンスタイプ:db.m5.large
- ストレージタイプ:汎用(SSD) 20GB
- DBパラメータグループ:default.postgres-11
ソースコード
計測用Lambdaのソースコードです。ランタイムにはNode.js 12.xを利用しました
const { performance } = require('perf_hooks'); const { Client } = require('pg'); const client = new Client({ user: '<ユーザー名>', host: '<RDS/RDS Proxyのエンドポイント>', database: '<DB名>', password: '<パスワード>', }) client.connect(); exports.handler = async (event) => { const t1 = performance.now(); const res = await client.query('select now()'); const t2 = performance.now(); console.log({ t1: t1, t2: t2, }) return res; };
後ほど分析に使用するため、SQL実行前後に performance.now();
を実行しています。
結果
CloudWatch Logs Insightsから以下のクエリを実行して集計しました
fields @timestamp, t1, t2, t2 - t1 | filter @message like /INFO/ | stats avg(t2 - t1), max(t2 - t1), min(t2 - t1),pct(t2 - t1, 90), pct(t2 - t1, 50), count(t2 - t1)
計測パターン | avg(t2 -t1) | max(t2 -t1) | min(t2 -t1) | 90パーセンタイル | 50%タイル |
---|---|---|---|---|---|
RDS直接接続 | 3.7202 | 36.359 | 2.9731 | 3.3582 | 3.1785 |
RDS Proxyあり | 6.3538 | 154.8245 | 4.0161 | 5.8598 | 4.456 |
RDS Proxyを挟むと平均で約2.6ms、90パーセンタイルで約2.5ms程度のオーバーヘッドが発生していることが分かります。「よくある質問」に記載されている5msという数値よりは優秀な結果が出ましたが、今回計測に使用したSQLがselect now()
というシンプルなSQLであり、結果セットのデータ量が少ないことが原因として考えられます。実際に業務で利用する際はもう少しデータ量が大きくなることが普通だと思います。データ量が増えると、クライアントとRDSの間にRDS Proxyを挟むことによって生じるラウンドトリップの増加によって、トータルのレイテンシーももう少し増加しそうです。「よくある質問」に記載されている平均5msという数値は妥当なラインではないでしょうか?
まとめ
RDS Proxyのデメリットの1つであるクエリのレイテンシーを計測してみましたが、「よくある質問」に記載されている平均5msという数値に近しい結果が出ました。RDS Proxyの採用有無を検討する際は「よくある質問」に記載されている平均5msのオーバーヘッドを念頭に検討すると良さそうです。また、アプリケーションの特性によっても影響度合いが変わってくるので、その点も注意が必要です。アプリケーションからのSQL発行回数が少ない場合は対したオーバーヘッドにはなりませんが、1回の処理でSQLを10回発行するようなアプリケーションだと10 × 5msでトータル50msの遅延となります。
こういった特性を頭に入れながら、適切なアーキテクチャを選定できるように心がけましょう。