Docs Menu
Docs Home
/
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

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

  • 多数のシャードを含むシャーディングされたクラスターに接続する 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/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 環境変数を設定する。

#include <mongoc/mongoc.h>
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();
}
#include <aws/core/Aws.h>
#include <aws/lambda-runtime/runtime.h>
#include <bsoncxx/json.hpp>
#include <mongocxx/client.hpp>
#include <mongocxx/instance.hpp>
#include <mongocxx/uri.hpp>
#include <mongocxx/options/client.hpp>
#include <mongocxx/options/server_api.hpp>
#include <mongocxx/exception/exception.hpp>
#include <cstdlib>
#include <iostream>
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;
}
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"));
}
@Override
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()
}
}
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(())
}
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()
}
}

戻る

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

項目一覧