Join us Sept 17 at .local NYC! Use code WEB50 to save 50% on tickets. Learn more >
MongoDB Event
Docs 菜单
Docs 主页
/
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 地址。

    如果您不使用专用网络,请考虑使用具有已映射弹性 IP 地址的 NAT 网关连接到 Atlas 集群。否则,您必须允许所有 IP 地址(0.0.0.0/0)访问您的服务集群。

    警告

    0.0.0.0/0添加到您的 IP 访问列表中,这允许从公共互联网中的任何位置访问集群。在允许从任何位置进行访问时,请确保对所有数据库用户使用强式档案。

  • maxIdleTimeMS 设置为 60000 可在空闲时间达到 1 分钟后自动关闭连接。调整 maxIdleTimeMS 有助于减少无服务器函数发生超时错误的概率。

  • 设置统一 AWS 访问权限,并尽可能使用 AWS IAM 身份验证。

    您可以使用 AWS IAM 角色连接到Atlas集群,而不是在Lambda中硬编码您的凭证。任何访问您的 AWS Lambda环境的人都可以查看硬编码凭证,这可能会带来安全风险。使用 AWS IAM身份验证, Atlas可通过假定的 IAM角色访问 AWS Lambda ,因此您无需在连接字符串中提供凭证。

    Atlas支持对运行MongoDB版本7.0或更高版本的集群进行Amazon Web Services IAM身份验证。如果您的集群符合这些要求,则强烈建议对Lambda连接使用Amazon Web Services IAM身份验证。

  • 分配给 Lambda 函数的内存量默认为 128 MB。您可将分配给 Lambda 函数的内存量配置为 128 MB 到 10,240 MB 之间。请务必分配足够的内存。增大内存以增加可用虚拟 CPU 的内存量并提高 MongoDB 驱动程序性能。要了解详情,请参阅内存和计算能力

  • 设置 AWS_STS_REGIONAL_ENDPOINTSAWS_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()
}
}

后退

故障排除

在此页面上