API GWのバックエンドにData API経由でselect pg_sleep(10)を実行するだけのLambdaを紐づけ、Lambdaのタイムアウトは15秒に設定、heyコマンドを使って200並列でAPI GWにアクセスします。, 100/200が200OKで正常終了、100/200が502でエラーになっています。, 200並列でアクセスしましたが、Data API用のコネクションは100までしか確保されていないようです。, この状態でCloud Watch Logsのログにmax_connections超過のログが出ていないか確認しましたが、max_connections超過のログは出力されていませんでした。 社内で需要がありそうだったので、RDS Proxyの基本動作について簡単にまとめてみました。クライアントからの最大同時接続数を1に設定したRDSに対してRDS Proxyを構成し、クライアントアプリケーションに見立てたEC2からいくつかのパターンで接続を試行した結果をまとめています。, その他通信に必要になるセキュリティグループやサブネットは適宜設定しています。また、検証のため事前にproxy_userという非マスターユーザーを作成しています。, まずは簡単におさらいから。RDS Proxyを利用するメリットの1つとして、アプリケーションからみた論理的なDB接続数を実際のDB接続数より多く見せかけることができる というメリットがあります。例えば2つのクライアントが同時にRDS Proxyに接続している場合、アプリケーションからみたDB接続数は2つですが、RDS Proxyがコネクションプールをよしなに管理することで、実際のRDS Proxy RDS間のDB接続は1つしか消費しない。といった構成が可能になります。このあたりの詳細はこちらの資料で詳しく解説しているので、よければ参考にして下さい。, まずは意図通りに設定できているか、確認の意味を含めてRDS Proxyを介さずにEC2から直接RDSに接続してみます。, では、現在psqlで接続中のシェルとは別のシェルからpsqlで接続を試みましょう。, 同時接続数の上限を超過したため、接続エラーとなりました。意図通り動作していそうです。, ここからはpsqlの接続先をRDS Proyxのエンドポイントに変更していくつかのパターンを試してみます。, 1つ目のシェルからRDS Proxyに接続したまま、2つ目のシェルからもRDS Proxyに接続してみましょう。, 無事に実行できました。1つ目のシェル、2つ目のシェル共どちらから確認しても、DBユーザー:proxy_userの使用しているDB接続はクライアントのIPアドレス、ポート番号が同一であり、EC2 RDS Proxy間の2つのpsql接続はRDS Proxy RDS間の1つの接続を共有していることが分かります。, 今度は1つ目のpsql接続、2つ目のpsql接続連続でSQLを実行してみましょう。, 1つ目のpsqlがpg_sleep(3)を実行している3秒間はバックエンドのRDS Proxy RDSの接続が1つ目のpsqlに割り当てられているため、2つ目のpsqlはWAIT状態になっていることが分かります。, いい感じですね!アプリケーションに対してRDSの最大同時接続数以上の可用性を提供できそうです。, トランザクションを利用するとどうなるでしょうか?先ほどと同様psqlからRDS Proxyに対して2つの接続を確立し、まず1つ目のpsqlでBEGINします。, 今度は約10秒後にタイムアウトエラーとなります。1つ目のpsqlがトランザクション実行中のため、2つ目のpsqlにDB接続を割り当てることができず、RDS Proxyのパラメータ「接続借用タイムアウト」で設定した10秒経過後にエラーが返却されたというわけです。実験が終わったので、1つめのpsqlのトランザクションはROLLBACKしておきましょう。, ロングトランザクションを実行するようなワークロードはRDS Proxyの恩恵を受けづらいことが分かります。, 今度はRDS Proyの注意点である「ピン留め」の動作を確認してみます。「ピン留め」とはRDS ProxyにプールされたDB接続が特定のクライアントに固定され、複数のクライアント間で共有できなくなる現象のことです。詳細は公式ドキュメントをご参照下さい。, https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/rds-proxy.html#rds-proxy-pinning, 先ほどと同様psqlからRDS Proxyに対して2つの接続を確立し、1つ目のpsql接続からPrepared Statementを利用してみましょう。, 今度は即座にエラーが返却されました。1つの目のpsqlにRDS Proxy RDS間の接続が「ピン留め」されたことで、2つ目のpsql接続用に割り当てるためのDB接続がコネクションプールから枯渇したためです。新たにRDS Proxy RDS間のDB接続をOPENしようとしても、最大同時接続数に到達しているため新規のDB接続がOPENできずエラーが返却されるのです。, 1つ目のpsql接続からPrepared StatementをDEALLOCATEするとどうでしょう?, Lambdaを使うユースケースでは稀かもしれませんが、EC2やECSでアプリを稼働させる場合は何らかのアプリケーションフレームワークを利用することが多いでしょう。アプリケーションフレームワークはセキュリティ対策等の理由でDBアクセス時に自動的にPrepared Statementを利用することも多いと思います。このあたりの特性をしっかり理解しておかないとRDS Proxyのメリットを享受できないばかりか、環境を改悪することにもなりかねないので、このあたりの挙動にはよーく注意しておきたいですね。何らかのアプリケーションフレームワーク on Fargate & RDSの環境にRDS Proxyを追加導入した結果、レイテンシーを悪化させただけで何もメリットが得られなかった。なんて悲しい事件が起きそうです。, RDS Proxyの基本動作について簡単にまとめてました。次回はもう少し掘り下げた内容でピン留め周りの挙動を検証してみようと思います。お楽しみに!, max_connections: 9 バックグラウンドでrdsadminユーザー、rdsproxyadminユーザーがDBに接続するのを考慮して9に設定しています。今回の環境であればmax_connectionsを9に設定することで非マスターユーザーからの同時接続数を1に制限することができます。. CX事業本部の岩田です。 なぜアンチパターンなのか. 今回はこのRDS Proxyを使用して今までアンチパターンとされていたLambdaからRDSへのアクセスを実際に試してつまずいた部分を共有したいと思います。, LambdaからRDSへのアクセスがアンチパターンと言われる最大の理由は同時接続数の上限です。 こんにちは、オカザキです。 VPC Lambdaのコールドスタート改善によって影が薄くなった感のあるData APIですが、同時接続数の問題に対してはData APIの方が有利な面があるかもしれません。Data APIの管理する接続数はmax_connectionsよりもある程度少ない数値(今回の構成だとmax_connections180に対して100)になるようなので、VPC Lambda × Auroraより有利になるかはワークロード次第と言えそうです。, 2019/11/22追記 Lambdaはリクエストごとに起動するためRDSのコネクションの上限数など気にせず起動するしてそれぞれのLambdaにてRDSに対してコネクションを張ろうとします。 Amazon RDS は、大文字と小文字が区別されるファイルシステムを使用するため、lower_case_table_names サーバーパラメータの値を 2 ([names stored as given but compared in lowercase]) に設定することはできません。以下は、Amazon RDS の MySQL DB インスタンスでサポート … こちらもprefixを削除したログを乗せておきます。, その後5分ほど経過した後disconnection: session time: 0:05:31.980...の部分でDBから切断しています。このことから、Data APIはSQL発行後も内部的にはDB接続を維持しているということが分かります。Data APIの基盤がpgpool-IIのような中間層として働いているようです。, 先ほどの検証はData APIから1回だけSQLを発行して終了しました。ログを確認するとData APIで指定したSQL以外にも色々なSQLが発行されていたので、インスタンス一時停止からの復旧時やData APIが内部的に使い回す接続確立時の初期化処理でも色々とSQLを発行していそうです。このあたりの基板側で自動発行しているSQLを見分けるために、今度は5分の間隔を空けずに何度かData APIからSQLを発行しログを確認してみます。, 結果は以下のようになりました。 実行タイムアウト時間が短かったのかと思い、30秒に伸ばしたりしましたが結果は同じくタイムアウトしてしまいました。 ~~最初にRDSをポチポチとたてて満足して放置していたら5,000円ほどの課金が発生したのはまた別の話です…~~, RDS Proxyを本稼働で使えるようになったら今後更にサーバーレスアーキテクチャが主流になっていくのではないでしょうか。 クライアントからの最大同時接続数を1に設定したRDSに対してRDS Proxyを構成し、クライアントアプリケーションに見立てたEC2からいくつかのパターンで接続を試行した結果をまとめています。 環境. LambdaからRDSに接続する時に、Lambdaでは全てのプロセスが独立してしまうので、connectionも使いまわすことが出来ません。 このため、Lambdaに対する同時接続数を増やしていくと、RDS側でconnection数が上限を超えた時にエラーになります。 エンドポイントをRDS Proxyとせず、直でRDSのエンドポイントとすると問題なく接続できたことからRDS Proxyへの接続に何かしら問題あることがわかりました。, AWS公式のユーザーガイドを読むとどうやらRDSと同じVPC内にLambda関数を配置する必要があったようです。(「プロキシへの接続の検証」参照), Lambda関数のVPC設定をRDSを作成したVPCと同一VPC内に設定してあげることで、無事RDS Proxyを経由してRDSに接続することができました。, 公式ドキュメントではNode.jsを用いて接続していましたが、個人的にPythonの方が好きだったのでPythonにて実装しました。, AWSの機能でプレビュー版を初めて使いましたがワクワクしながら環境構築することができました。, 3年近くAWSを利用していましたがRDS自体は触るのが初めてだった為勉強になることが多かったです。 LambdaからRDSへのアクセスがアンチパターンと言われる最大の理由は同時接続数の上限です。 Lambdaはリクエストごとに起動するためRDSのコネクションの上限数など気にせず起動するしてそれぞれのLambdaにてRDSに対してコネクションを張ろうとします。 追加検証の結果、さらに並列度を上げていくことでmax_connectionsを使い切れることが分かりました。, Aurora ServerlessのData APIがプーリングするコネクション数について調べてみた, このあたりの情報も踏まえた上でVPC Lambdaを使うのか、Aurora ServerlessのData APIを使うのか、適切な判断をして頂ければと思います。 検証1と同様にSHOW TRANSACTION ISOLATION LEVELを実行するセッションが接続後すぐに切断されていたので、その分のログは省略しています。, を繰り返していそうです。SELECT n.nspname =...というSQLとSELECT typinput='array_in...というSQLはData APIの初回実行時のみ発行されています。レスポンスをJSON形式で生成するために必要なメタデータを取得しているとかでしょうか?, SHOW TRANSACTION ISOLATION LEVEL等のSQLを発行しているのはData API用の初期化処理なのか、インスタンスが一時停止から復旧した際固有の処理なのかを切り分けたいと思います。EC2から普通にpsqlでAuroraに接続し、Data API用のセッションを強制的に切断します。, まずpg_stat_activityからData API用セッションのPIDを確認します。, pg_terminate_backendで強制終了します。※pg_cancel_backendだと止まってくれませんでした。, pg_stat_activityからセッションが切断されたことを確認し、再度Data APIを叩いてログを確認してみます。, SHOW TRANSACTION ISOLATION LEVELから始まる一連のSQLが実行されたログはありませんでした。つまりこの一連のSQLはData API用の接続確立時ではなく、DBインスタンスが一時停止から復旧した際に実行される初期処理のようです。, もう少しData APIの管理用コネクションについて深掘りしてみようと思います。 もちろん最初にRDBが必要なのか?!RDBを使っても問題のないユースケースなのか?!という点を良くご検討下さい。, DBエンジン: Aurora PostgreSQL (compatible with PostgreSQL 10.7), 101以上の接続要求が来た場合はエラーを返却するのではなく、プールしている接続が空くまで待機する. 見やすいようにprefixを削除すると以下のようになります。, その後10.1.13.68というIPが接続し、以下の順番でSQLを実行しています。, 発行しているSQLの内容からしてこちらのセッションがData APIのセッションのようです。 そのため、コネクションの上限を超えたLambdaからのアクセスはRDSアクセス時にエラーとなってしまいます。, 今回発表されたRDS Proxyを使うことでRDSに確立した接続をプール・共有してコネクションが上限を超えないよう管理しているようです。, 公式のドキュメント通りに環境を作成し、Lambdaを実行しましたが以下のエラーとなりました。, “errorMessage”: “2020-03-24T12:56:44.589Z 2bc87ca4-4998-4403-8202-b1ef58dcd91f Task timed out after 3.00 seconds”, Lambdaの実行タイムアウトとなっていました。 今回検証に利用した環境です。 RDS for PostgreSQL 11.8-R1 2019年の秋頃、AWSよりRDS Proxyの発表がありました。 検証5の結果から予測した通り、Data APIが管理する接続数を超過したリクエストに関しては一旦待機状態になり、接続が空き次第実行されるという動作で間違い無さそうです。, Data APIの裏側ではpgpool-IIのようなプロキシ型のコネクションプーリング機構が動作していることが確認できました。 CX事業本部の岩田です。 Aurora ServerlessのData APIがリリースされた際に「Lambda -> RDSの最大同時接続数の問題が改善される」といった話を聞くことが多かったのですが、なぜhttpsのエンドポイントができただけで同時接続数の問題が解決するのか、いまいち良く分かりませんでした。 Lambdaの方のログを確認してみると、、、, こんなログが出ていました。このことから、今回の検証環境の設定ではAurora Data APIの裏側で, 検証5でLambdaのタイムアウトが出ていたのでLambdaのタイムアウト設定を30秒に延長して再トライしてみました。, といいう結果に終わりました。