ベストプラクティス
次のベストプラクティスを使用して、 AWS Lambda と Atlas 間の接続を適切に管理します。
Amazon Web Services Lambdaハンドラー関数 の外部でMongoDBサーバーへのクライアントを定義します。
関数を呼び出すたびに新しい
MongoClient
オブジェクトを定義しないでください。定義すると、ドライバーは関数を呼び出すごとに新しいデータベース接続を作成します。こうなると、コストが高くなり、アプリケーションがデータベース接続制限を超えてしまう可能性があります。新しいMongoClient
を定義するときは、以下を行う必要があります。MongoClient
オブジェクトを一度だけ作成します。オブジェクトを保存し、関数の呼び出し全体で
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 詳細については、「接続オプション 」を参照してください。
多数のシャードを含むシャーディングされたクラスターに接続する 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 詳細については、「接続オプション 」を参照してください。
多数のシャードを含むシャーディングされたクラスターに接続する 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 詳細については、「接続オプション 」を参照してください。
多数のシャードを含むシャーディングされたクラスターに接続する 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/0
を IP アクセス リストに追加すると、パブリック インターネットのどこからでもクラスターにアクセスできるようになります。どこからでもアクセスを許可する場合は、すべてのデータベース ユーザーについて必ず強力な認証情報を使用してください。
maxIdleTimeMS を
60000
に設定すると、アイドルタイムが 1 分経過した後に接続が自動的に閉じられます。maxIdleTimeMS
を調整すると、サーバーレス関数からのタイムアウト エラーの発生を減らすことができます。
統合 AWS アクセスを設定し、可能な場合はAWS IAM 認証を使用します。
Lambdaで認証情報をハードコーディングする代わりに、 Amazon Web Services IAMロール を使用してAtlasクラスターに接続できますハードコードされた認証情報は、 Amazon Web Services Lambda環境にアクセスするすべてのユーザーが表示できるため、セキュリティ上のリスクが生じる可能性があります。 Amazon Web Services IAM認証では、Atlas は 想定された IAM ロール を通じて Amazon Web Services Lambda にアクセスします。そのため、接続文字列に認証情報は必要ありません。
Atlas は、 MongoDBバージョン 以降を実行中クラスターのAmazon Web Services IAM認証をサポートしています。7.0クラスターが要件を満たしている場合は、 Lambda接続にAmazon Web Services IAM認証を使用することを強くお勧めします。
Lambda 関数に割り当てられるメモリの量はデフォルトで 128MB になります。Lambda 関数に割り当てられるメモリの量は、128MB から 10,240MB の範囲で設定できます。十分なメモリを割り当ててください。メモリを増やして使用可能な仮想 CPU の量を増やすことで、MongoDB ドライバーのパフォーマンスを向上させます。詳しくは「メモリとコンピューティング能力」を参照してください。
AWS_STS_REGIONAL_ENDPOINTS および AWS_REGION 環境変数を設定する。
接続例
void lambda_handler () { bson_error_t error; mongoc_init(); // Parse URI char *uri_string = "your-mongodb-atlas-connection-string"; mongoc_uri_t *uri = mongoc_uri_new_with_error (uri_string, &error); if (!uri) { fprintf (stderr, "Failed to parse URI: %s\n", error.message); return; } // Create client mongoc_client_t *client = mongoc_client_new_from_uri_with_error(uri, &error); if (!client) { fprintf(stderr, "Failed to create client: %s\n", error.message); return; } // Perform client operations here // Cleanup mongoc_client_destroy(client); mongoc_uri_destroy (uri); mongoc_cleanup(); }
using namespace aws::lambda_runtime; class ExampleAwsHandler { private: mongocxx::client mongo_client; client CreateMongoClient() { mongocxx::uri uri("mongodb://<hostname>:<port>/?authMechanism=MONGODB-AWS"); mongocxx::options::server_api server_api_options(mongocxx::options::server_api::version::k_version_1); mongocxx::options::client client_options; client_options.server_api_opts(server_api_options); return client(uri, client_options); } public: ExampleAwsHandler() : mongo_client(CreateMongoClient()) { } std::string HandleRequest() { try { using bsoncxx::builder::basic::kvp; using bsoncxx::builder::basic::make_document; auto db = mongo_client["my_database"]; auto command = make_document(kvp("hello", 1)); auto result = db.run_command(command.view()); return bsoncxx::to_json(result); } catch (const mongocxx::exception &e) { std::cerr << "MongoDB Exception: " << e.what() << std::endl; return "{}"; } } }; static invocation_response my_handler(invocation_request const &) { ExampleAwsHandler handler; std::string response = handler.HandleRequest(); return invocation_response::success(response, "application/json"); } int main() { Aws::SDKOptions options; Aws::InitAPI(options); { mongocxx::instance instance{}; run_handler(my_handler); } Aws::ShutdownAPI(options); return 0; }
Amazon Web ServicesAmazon Web Services IAM 認証
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(); }
import ( "context" "os" runtime "github.com/aws/aws-lambda-go/lambda" "go.mongodb.org/mongo-driver/v2/mongo" "go.mongodb.org/mongo-driver/v2/mongo/options" ) var client, err = mongo.Connect(options.Client().ApplyURI(os.Getenv("MONGODB_URI"))) func HandleRequest(ctx context.Context) error { if err != nil { return err } return client.Ping(context.TODO(), nil) }
import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoClients; import org.bson.Document; public class ExampleAwsLambdaHandler implements RequestHandler<String, String> { private final MongoClient client; public ExampleAwsLambdaHandler() { client = MongoClients.create(System.getenv("MONGODB_URI")); } public String handleRequest(final String input, final Context context) { return client.getDatabase("admin").runCommand(new Document("ping", 1)).toJson(); } }
import com.mongodb.kotlin.client.coroutine.MongoClient import com.mongodb.kotlin.client.coroutine.MongoDatabase import org.bson.Document import kotlinx.coroutines.runBlocking import com.amazonaws.services.lambda.runtime.Context import com.amazonaws.services.lambda.runtime.RequestHandler class ExampleAwsLambdaHandler : RequestHandler<String, String> { private val client: MongoClient = MongoClient.create(System.getenv("MONGODB_URI")) override fun handleRequest(input: String, context: Context): String = runBlocking { val database: MongoDatabase = client.getDatabase("admin") val command = Document("ping", 1) val result = database.runCommand(command) result.toJson() } }
import com.mongodb.kotlin.client.MongoClient import com.mongodb.kotlin.client.MongoDatabase import org.bson.Document import com.amazonaws.services.lambda.runtime.Context import com.amazonaws.services.lambda.runtime.RequestHandler class ExampleAwsLambdaHandler : RequestHandler<String, String> { private val client: MongoClient = MongoClient.create(System.getenv("MONGODB_URI")) override fun handleRequest(input: String, context: Context): String { val database: MongoDatabase = client.getDatabase("admin") val command = Document("ping", 1) val result = database.runCommand(command) return result.toJson() } }
Amazon Web ServicesAmazon Web Services IAM 認証
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")
Amazon Web ServicesAmazon Web Services IAM 認証
# 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
AWS IAM 認証
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) } 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) } async fn main() -> Result<(), lambda_runtime::Error> { let service = service_fn(handler); lambda_runtime::run(service).await?; Ok(()) }
import org.mongodb.scala.{MongoClient, Document} import scala.concurrent.Await import scala.concurrent.duration.Duration import com.amazonaws.services.lambda.runtime.Context import com.amazonaws.services.lambda.runtime.RequestHandler class ExampleAwsLambdaHandler extends RequestHandler[String, String] { private val client: MongoClient = MongoClient(System.getenv("MONGODB_URI")) override def handleRequest(input: String, context: Context): String = { val database = client.getDatabase("admin") val command = Document("ping" -> 1) val futureResult = database.runCommand(command).toFuture() val result = Await.result(futureResult, Duration(30, "second")) result.toJson() } }