AWS SAP試験対策 #3
問題(ざっくり)
あるWebアプリケーションは、Lambda関数でAurora MySQLデータベースをクエリします。データベースは複数のリードレプリカで構成されています。アクセスが集中する期間では、アプリケーションのパフォーマンスが低下します。アプリケーションが多くのデータベース接続を行うために遅延が発生している模様です。パフォーマンスを向上させるにはどうすればいいですか?
① ゲートウェイロードバランサーを作成して、Auroraリードレプリカ間で接続を分散する。
② Auroraサーバーレスデータベースクラスターで自動スケーリングを使用する。
③ RDS Proxy接続プールをAuroraデータベースのクラスターエンドポイントに接続する。
④ データベース接続を開くためのLambda関数コードをイベントハンドラーの外に置く。
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
回答
④ データベース接続を開くためのLambda関数コードをイベントハンドラーの外に置く。
要点解説
問題文中に、今回の事象発生要因が「アプリケーションが多くのデータベース接続を行うため」と書かれています。
要するに、Lambda関数が何度もデータベースへアクセスしていることが原因、ということです。
Lambda関数は、1つのイベントごとに個別の実行環境(コンテナ)が用意され、その中で実行されます。
イベントハンドラー関数内でデータベース接続をした場合、そのイベントが終了するとデータベース接続も終了します。
したがって、関数が実行されるたびに毎回新しい接続・破棄するオーバヘッドが発生し、パフォーマンスが低下します。
一方で、データベース接続を関数コードの外部(グローバルコンテキスト)に置くことで、以下の利点がある。
- コネクションプーリングの実施:データベースへの接続を確保しておいて、それをアプリケーションで使いまわす仕組み。
- コールドスタートの遅延改善:上記で接続が事前に確保されているので、時間短縮になる。
- メモリ効率の改善:個別のイベントごとに接続を作成する必要がなくなるため。
したがって、Lambdaアプリケーションのボトルネックを解決し、データベースとのやり取りを最適化するための適切な対処方法として④が正解です。
(RDS Proxyと組み合わせて使用することがより良い構成のようです。以下参照)
以下に簡単なサンプルコードを記述しておきます。
import boto3
import pymysql
# グローバル コンテキストでデータベース接続を初期化。
# 認証情報は本来、Secrets Managerなどで管理するべきです。
rds_client = boto3.client('rds-data')
db_cluster_arn = 'arn:aws:rds:ap-northeast-1:123456789012:cluster:my-db-cluster'
db_credentials = rds_client.generate_db_auth_token(DBHostname="my-db-cluster.cluster-xxxxx.ap-northeast-1.rds.amazonaws.com", Port=3306, DBUsername="my_user")
db_connection = pymysql.connect(host="my-db-cluster.cluster-xxxxx.ap-northeast-1.rds.amazonaws.com", user=db_credentials['AuthToken'], password="", port=3306, database="my_db")
def lambda_handler(event, context):
# グローバルで初期化された接続を使用
with db_connection.cursor() as cur:
# クエリを実行
...
# 返す値を処理
...
return response
他選択肢の不正解理由解説
① ゲートウェイロードバランサーを作成して、Auroraリードレプリカ間で接続を分散する。
→ゲートウェイロードバランサ―は管理対象仮想アプライアンス(ファイアウォールなど)をデプロイ・スケーリング・管理できます。データベースには使用しません。
② Auroraサーバーレスデータベースクラスターで自動スケーリングを使用する。
→Amazon Aurora用のオンデマンドのオートスケーリング設定で、ワークロードをモニタリングし、データベースの容量を調整するプロセスを自動化しやすくなります。ただし、接続管理には役立ちません。
③ RDS Proxy接続プールをAuroraデータベースのクラスターエンドポイントに接続する。
→RDS Proxyと共に使用するのは良いユースケースです。RDS Proxyを使用すると、アプリケーションでデータベース接続をプール(=蓄える)および共有して、アプリケーションのスケーリング能力を向上させることができます。
ただしここではAuroraデータベースのリードエンドポイントに接続する必要があります。