Docs Menu
Docs Home
/
MongoDB Atlas
/

AWS Lambda で接続を管理する

項目一覧

  • ベストプラクティス
  • 接続例

次のベストプラクティスを使用して、 AWS Lambda と Atlas 間の接続を適切に管理します。

  • AWS Lambda ハンドラー関数の外部で MongoDB サーバーへのクライアントを定義します。

    関数を呼び出すたびに新しい MongoClient オブジェクトを定義しないでください。定義すると、ドライバーは関数を呼び出すごとに新しいデータベース接続を作成します。こうなると、コストが高くなり、アプリケーションがデータベース接続制限を超えてしまう可能性があります。新しい MongoClient を定義するときは、以下を行う必要があります。

    1. MongoClient オブジェクトを一度だけ作成します。

    2. オブジェクトを保存し、関数の呼び出し全体で MongoClient を再利用できるようにします。

    この接続例では、既存のデータベース接続を再利用して、データベースとの通信を高速化し、データベースへの接続数をアプリケーション トラフィックに関して適切なレベルに維持します。

  • 多数のシャードを含むシャーディングされたクラスターに接続する Lambda 関数がある場合、パフォーマンスの問題が発生する可能性があります。たとえば、シャーディングされたクラスターが 10 個ある場合、ドライバーはデフォルトで 30 個の mongos インスタンスすべてに接続します。接続文字列に srvMaxHosts オプションを使用して、ドライバーが接続するホストの最大数を設定できます。ドライバーのパフォーマンスを向上させるには、 srvMaxHosts=3 を設定します。例えば、次のように設定できます。

    mongodb+srv://<db_username>:<db_password>@<clusterName>.mongodb.net/?retryWrites=true&w=majority&srvMaxHosts=3

    詳細については、「接続オプション 」を参照してください。

  • 多数のシャードを含むシャーディングされたクラスターに接続する Lambda 関数がある場合、パフォーマンスの問題が発生する可能性があります。たとえば、シャーディングされたクラスターが 10 個ある場合、ドライバーはデフォルトで 30 個の mongos インスタンスすべてに接続します。接続文字列に srvMaxHosts オプションを使用して、ドライバーが接続するホストの最大数を設定できます。ドライバーのパフォーマンスを向上させるには、 srvMaxHosts=3 を設定します。例えば、次のように設定できます。

    mongodb+srv://<db_username>:<db_password>@<clusterName>.mongodb.net/?retryWrites=true&w=majority&srvMaxHosts=3

    詳細については、「接続オプション 」を参照してください。

  • 多数のシャードを含むシャーディングされたクラスターに接続する Lambda 関数がある場合、パフォーマンスの問題が発生する可能性があります。たとえば、シャーディングされたクラスターが 10 個ある場合、ドライバーはデフォルトで 30 個の mongos インスタンスすべてに接続します。接続文字列に srvMaxHosts オプションを使用して、ドライバーが接続するホストの最大数を設定できます。ドライバーのパフォーマンスを向上させるには、 srvMaxHosts=3 を設定します。例えば、次のように設定できます。

    mongodb+srv://<db_username>:<db_password>@<clusterName>.mongodb.net/?retryWrites=true&w=majority&srvMaxHosts=3

    詳細については、「接続オプション 」を参照してください。

  • ハンドラーが最後の引数としてコールバックを取る場合は、 AWS Lambda Context オブジェクトの callbackWaitsForEmptyEventLoop プロパティを false に設定します。

    context.callbackWaitsForEmptyEventLoop = false;

    これにより、Lambda 関数は、MongoDB データベース接続を閉じることなく、結果を呼び出し元に返すことができます。このプロパティの設定は非同期ハンドラーには適用されません。

  • 多数のシャードを含むシャーディングされたクラスターに接続する Lambda 関数がある場合、パフォーマンスの問題が発生する可能性があります。たとえば、シャーディングされたクラスターが 10 個ある場合、ドライバーはデフォルトで 30 個の mongos インスタンスすべてに接続します。接続文字列に srvMaxHosts オプションを使用して、ドライバーが接続するホストの最大数を設定できます。ドライバーのパフォーマンスを向上させるには、 srvMaxHosts=3 を設定します。例えば、次のように設定できます。

    mongodb+srv://<db_username>:<db_password>@<clusterName>.mongodb.net/?retryWrites=true&w=majority&srvMaxHosts=3

    詳細については、「接続オプション 」を参照してください。

  • 多数のシャードを含むシャーディングされたクラスターに接続する Lambda 関数がある場合、パフォーマンスの問題が発生する可能性があります。たとえば、シャーディングされたクラスターが 10 個ある場合、ドライバーはデフォルトで 30 個の mongos インスタンスすべてに接続します。接続文字列に srvMaxHosts オプションを使用して、ドライバーが接続するホストの最大数を設定できます。ドライバーのパフォーマンスを向上させるには、 srvMaxHosts=3 を設定します。例えば、次のように設定できます。

    mongodb+srv://<db_username>:<db_password>@<clusterName>.mongodb.net/?retryWrites=true&w=majority&srvMaxHosts=3

    詳しくは「MongoDB に接続するためのツール」を参照してください。

  • 多数のシャードを含むシャーディングされたクラスターに接続する Lambda 関数がある場合、パフォーマンスの問題が発生する可能性があります。たとえば、シャーディングされたクラスターが 10 個ある場合、ドライバーはデフォルトで 30 個の mongos インスタンスすべてに接続します。接続文字列に srvMaxHosts オプションを使用して、ドライバーが接続するホストの最大数を設定できます。ドライバーのパフォーマンスを向上させるには、 srvMaxHosts=3 を設定します。例えば、次のように設定できます。

    mongodb+srv://<db_username>:<db_password>@<clusterName>.mongodb.net/?retryWrites=true&w=majority&srvMaxHosts=3

    詳細については、URI オプションを参照してください。

  • 多数のシャードを含むシャーディングされたクラスターに接続する Lambda 関数がある場合、パフォーマンスの問題が発生する可能性があります。たとえば、シャーディングされたクラスターが 10 個ある場合、ドライバーはデフォルトで 30 個の mongos インスタンスすべてに接続します。接続文字列に srvMaxHosts オプションを使用して、ドライバーが接続するホストの最大数を設定できます。ドライバーのパフォーマンスを向上させるには、 srvMaxHosts=3 を設定します。例えば、次のように設定できます。

    mongodb+srv://<db_username>:<db_password>@<clusterName>.mongodb.net/?retryWrites=true&w=majority&srvMaxHosts=3

    詳細については、「接続オプション 」を参照してください。

  • Atlas クラスターへのネットワーク アクセスを制限します。

    Atlas クラスターと AWS Lambda 関数間の ネットワークピアリング接続 、またはプライベートエンドポイントを使用して、プライベートネットワーク経由で Atlas クラスターに接続し、IP アクセスリストからプライベート IP アドレスのみを許可できるようにします。

    プライベートネットワークを使用しない場合は、マッピングされた Elastic IP アドレスを使用して NAT ゲートウェイ経由で Atlas クラスターに接続することを検討してください。それ以外の場合は、すべての IP アドレス (0.0.0.0/0) にサービス クラスターへのアクセスを許可する必要があります。

    警告

    0.0.0.0/0IP アクセス リストに追加すると、パブリック インターネットのどこからでもクラスターにアクセスできるようになります。どこからでもアクセスを許可する場合は、すべてのデータベース ユーザーについて必ず強力な認証情報を使用してください。

  • maxIdleTimeMS60000 に設定すると、アイドルタイムが 1 分経過した後に接続が自動的に閉じられます。maxIdleTimeMS を調整すると、サーバーレス関数からのタイムアウト エラーの発生を減らすことができます。

  • 統合 AWS アクセスを設定し、可能な場合はAWS IAM 認証を使用します。

    Lambda で認証情報をハードコーディングする代わりに、AWS IAM ロールを使用して Atlas クラスターに接続できます。ハードコードされた認証情報は、AWS Lambda 環境にアクセスするすべてのユーザーが閲覧できるため、セキュリティ上のリスクが生じる可能性があります。AWS IAM 認証では、Atlas は想定された IAM ロールを通じて AWS Lambda にアクセスします。そのため、接続文字列に認証情報は必要ありません。

    Atlas は、MongoDB バージョン 5.0 以降を実行しているクラスターのAWS IAM 認証をサポートしています。クラスターが要件を満たしている場合は、Lambda 接続にAWS IAM 認証を使用することを強くお勧めします。

  • Lambda 関数に割り当てられるメモリの量はデフォルトで 128MB になります。Lambda 関数に割り当てられるメモリの量は、128MB から 10,240MB の範囲で設定できます。十分なメモリを割り当ててください。メモリを増やして使用可能な仮想 CPU の量を増やすことで、MongoDB ドライバーのパフォーマンスを向上させます。詳しくは「メモリとコンピューティング能力」を参照してください。

  • AWS_STS_REGIONAL_ENDPOINTS および AWS_REGION 環境変数を設定する。

string username = Environment.GetEnvironmentVariable("AWS_ACCESS_KEY_ID");
string password = Environment.GetEnvironmentVariable("AWS_SECRET_ACCESS_KEY");
string awsSessionToken = Environment.GetEnvironmentVariable("AWS_SESSION_TOKEN");
var awsCredentials =
new MongoCredential("MONGODB-AWS", new MongoExternalIdentity(username), new PasswordEvidence(password))
.WithMechanismProperty("AWS_SESSION_TOKEN", awsSessionToken);
var mongoUrl = MongoUrl.Create($"<MONGODB_URI>");
var mongoClientSettings = MongoClientSettings.FromUrl(mongoUrl);
mongoClientSettings.Credential = awsCredentials;
mongoClientSettings.ServerApi = new ServerApi(ServerApiVersion.V1, strict: true);
return new MongoClient(mongoClientSettings);
private static MongoClient MongoClient { get; set; }
private static MongoClient CreateMongoClient()
{
var mongoClientSettings = MongoClientSettings.FromConnectionString($"<MONGODB_URI>");
mongoClientSettings.ServerApi = new ServerApi(ServerApiVersion.V1, strict: true);
return new MongoClient(mongoClientSettings);
}
static ShareMongoClientLambdaHandler()
{
MongoClient = CreateMongoClient();
}
public string HandleRequest(ILambdaContext context)
{
var database = MongoClient.GetDatabase("db");
var collection = database.GetCollection<BsonDocument>("coll");
var result = collection.Find(FilterDefinition<BsonDocument>.Empty).First();
return result.ToString();
}
var client, err = mongo.Connect(context.TODO(), options.Client().ApplyURI(os.Getenv("MONGODB_URI")))
func HandleRequest(ctx context.Context) error {
if err != nil {
return err
}
return client.Ping(context.TODO(), nil)
}
public class ExampleAwsLambdaHandler implements RequestHandler<String, String> {
private final MongoClient client;
public ExampleAwsLambdaHandler() {
client = MongoClients.create(System.getenv("MONGODB_URI"));
}
@Override
public String handleRequest(final String input, final Context context) {
return client.getDatabase("admin").runCommand(new Document("ping", 1)).toJson();
}
}
const { MongoClient } = require('mongodb');
// Get the URI for the cluster then set AWS_ACCESS_KEY_ID as the username in the
// URI and AWS_SECRET_ACCESS_KEY as the password, then set the appropriate auth
// options. Note that MongoClient now auto-connects so no need to store the connect()
// promise anywhere and reference it.
const client = new MongoClient(process.env.MONGODB_URI, {
auth: {
username: process.env.AWS_ACCESS_KEY_ID,
password: process.env.AWS_SECRET_ACCESS_KEY
},
authSource: '$external',
authMechanism: 'MONGODB-AWS'
});
module.exports.handler = async function () {
const databases = await client.db('admin').command({ listDatabases: 1 });
return {
statusCode: 200,
databases: databases
};
};
const { MongoClient } = require('mongodb');
// MongoClient now auto-connects so no need to store the connect()
// promise anywhere and reference it.
const client = new MongoClient(process.env.MONGODB_URI);
module.exports.handler = async function () {
const databases = await client.db('admin').command({ listDatabases: 1 });
return {
statusCode: 200,
databases: databases
};
};
import os
from pymongo import MongoClient
client = MongoClient(host=os.environ["MONGODB_URI"])
def lambda_handler(event, context):
return client.db.command("ping")
# Require the driver library.
require "mongo"
# Create a Mongo::Client instance using AWS IAM authentication.
# CRITICAL: You must create the client instance outside the handler
# so that the client can be reused across function invocations.
client = Mongo::Client.new([ENV.fetch("MONGODB_HOST")],
auth_mech: :aws,
user: ENV.fetch("AWS_ACCESS_KEY_ID"),
password: ENV.fetch("AWS_SECRET_ACCESS_KEY"),
auth_mech_properties: {
aws_session_token: ENV.fetch("AWS_SESSION_TOKEN"),
},
database: ENV.fetch("MONGODB_DATABASE"))
def lambda_handler(event:, context:)
# Use the client to return the name of the configured database.
client.database.name
end
# Require the driver library.
require "mongo"
# Create a Mongo::Client instance.
# CRITICAL: You must create the client instance outside the handler
# so that the client can be reused across function invocations.
client = Mongo::Client.new(ENV.fetch("MONGODB_URI"))
def lambda_handler(event:, context:)
# Use the client to return the name of the configured database.
client.database.name
end
use lambda_runtime::{service_fn, LambdaEvent};
use mongodb::{
bson::doc,
options::{AuthMechanism, ClientOptions, Credential},
Client,
};
use serde_json::Value;
use tokio::sync::OnceCell;
// Initialize a global static MongoDB Client with AWS authentication. The following environment
// variables should also be set: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and, optionally,
// AWS_SESSION_TOKEN.
static MONGODB_CLIENT: OnceCell<Client> = OnceCell::const_new();
async fn get_mongodb_client() -> &'static Client {
MONGODB_CLIENT
.get_or_init(|| async {
let uri = std::env::var("MONGODB_URI")
.expect("MONGODB_URI must be set to the URI of the MongoDB deployment");
let mut options = ClientOptions::parse(&uri)
.await
.expect("Failed to parse options from URI");
let credential = Credential::builder()
.mechanism(AuthMechanism::MongoDbAws)
.build();
options.credential = Some(credential);
Client::with_options(options).expect("Failed to create MongoDB Client")
})
.await
}
// Runs a ping operation on the "db" database and returns the response.
async fn handler(_: LambdaEvent<Value>) -> Result<Value, lambda_runtime::Error> {
let client = get_mongodb_client().await;
let response = client
.database("db")
.run_command(doc! { "ping": 1 })
.await?;
let json = serde_json::to_value(response)?;
Ok(json)
}
#[tokio::main]
async fn main() -> Result<(), lambda_runtime::Error> {
let service = service_fn(handler);
lambda_runtime::run(service).await?;
Ok(())
}
use lambda_runtime::{service_fn, LambdaEvent};
use mongodb::{bson::doc, Client};
use serde_json::Value;
use tokio::sync::OnceCell;
// Initialize a global static MongoDB Client.
static MONGODB_CLIENT: OnceCell<Client> = OnceCell::const_new();
async fn get_mongodb_client() -> &'static Client {
MONGODB_CLIENT
.get_or_init(|| async {
let uri = std::env::var("MONGODB_URI")
.expect("MONGODB_URI must be set to the URI of the MongoDB deployment");
Client::with_uri_str(uri)
.await
.expect("Failed to create MongoDB Client")
})
.await
}
// Runs a ping operation on the "db" database and returns the response.
async fn handler(_: LambdaEvent<Value>) -> Result<Value, lambda_runtime::Error> {
let client = get_mongodb_client().await;
let response = client
.database("db")
.run_command(doc! { "ping": 1 })
.await?;
let json = serde_json::to_value(response)?;
Ok(json)
}
#[tokio::main]
async fn main() -> Result<(), lambda_runtime::Error> {
let service = service_fn(handler);
lambda_runtime::run(service).await?;
Ok(())
}

戻る

リージョン停止のシミュレーション