Menu Docs

Gerenciar conexões com AWS Lambda

Utilize as seguintes melhores práticas para gerenciar adequadamente as conexões entre a AWS Lambda e o Atlas:

  • Defina o cliente para o servidor MongoDB fora da função de manipulador AWS Lambda.

    Não defina um novo objeto MongoClient sempre que invocar a sua função. Isso faz com que o driver crie uma nova conexão de banco de dados com cada chamada de função. Isso pode ser caro e resultar em um aplicativo que exceda os limites de conexão do banco de dados. Ao definir um novo MongoClient, você deve:

    1. Crie uma vez o objeto MongoClient.

    2. Armazene o objeto para que sua função possa reutilizar o MongoClient em invocações de função.

    O Exemplo de conexão reutiliza as conexões de banco de dados existentes para acelerar a comunicação com o banco de dados e manter as contagens de conexão com o banco de dados em um nível razoável em relação ao tráfego do aplicativo.

  • Se você tiver uma função Lambda que se conecta a um cluster fragmentado com muitos shards, você pode enfrentar problemas de desempenho. Por exemplo, com um cluster de dez shards, o driver se conecta a todas as trinta instâncias mongos por padrão. Você pode usar a opção srvMaxHosts na sua string de conexão para definir o número máximo de hosts aos quais o driver se conecta. Para melhorar o desempenho do driver, defina srvMaxHosts=3. Por exemplo:

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

    Para saber mais, consulte Opções de conexão.

  • Se você tiver uma função Lambda que se conecta a um cluster fragmentado com muitos shards, você pode enfrentar problemas de desempenho. Por exemplo, com um cluster de dez shards, o driver se conecta a todas as trinta instâncias mongos por padrão. Você pode usar a opção srvMaxHosts na sua string de conexão para definir o número máximo de hosts aos quais o driver se conecta. Para melhorar o desempenho do driver, defina srvMaxHosts=3. Por exemplo:

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

    Para saber mais, consulte Opções de conexão.

  • Se você tiver uma função Lambda que se conecta a um cluster fragmentado com muitos shards, você pode enfrentar problemas de desempenho. Por exemplo, com um cluster de dez shards, o driver se conecta a todas as trinta instâncias mongos por padrão. Você pode usar a opção srvMaxHosts na sua string de conexão para definir o número máximo de hosts aos quais o driver se conecta. Para melhorar o desempenho do driver, defina srvMaxHosts=3. Por exemplo:

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

    Para saber mais, consulte Opções de conexão.

  • Se o seu manipulador receber uma chamada de resposta como último argumento, defina a propriedade callbackWaitsForEmptyEventLoop no objeto AWS Lambda Context como falso.

    context.callbackWaitsForEmptyEventLoop = false;

    Isso permite que uma função Lambda retorne seu resultado ao chamador sem exigir que a conexão do banco de dados MongoDB seja fechada. A definição dessa propriedade não é aplicável a manipuladores assíncronos.

  • Se você tiver uma função Lambda que se conecta a um cluster fragmentado com muitos shards, você pode enfrentar problemas de desempenho. Por exemplo, com um cluster de dez shards, o driver se conecta a todas as trinta instâncias mongos por padrão. Você pode usar a opção srvMaxHosts na sua string de conexão para definir o número máximo de hosts aos quais o driver se conecta. Para melhorar o desempenho do driver, defina srvMaxHosts=3. Por exemplo:

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

    Para saber mais, consulte Opções de conexão.

  • Se você tiver uma função Lambda que se conecta a um cluster fragmentado com muitos shards, você pode enfrentar problemas de desempenho. Por exemplo, com um cluster de dez shards, o driver se conecta a todas as trinta instâncias mongos por padrão. Você pode usar a opção srvMaxHosts na sua string de conexão para definir o número máximo de hosts aos quais o driver se conecta. Para melhorar o desempenho do driver, defina srvMaxHosts=3. Por exemplo:

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

    Para saber mais, consulte Ferramentas para conectar-se ao MongoDB.

  • Se você tiver uma função Lambda que se conecta a um cluster fragmentado com muitos shards, você pode enfrentar problemas de desempenho. Por exemplo, com um cluster de dez shards, o driver se conecta a todas as trinta instâncias mongos por padrão. Você pode usar a opção srvMaxHosts na sua string de conexão para definir o número máximo de hosts aos quais o driver se conecta. Para melhorar o desempenho do driver, defina srvMaxHosts=3. Por exemplo:

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

    Para saber mais, consulte Opções de URI.

  • Se você tiver uma função Lambda que se conecta a um cluster fragmentado com muitos shards, você pode enfrentar problemas de desempenho. Por exemplo, com um cluster de dez shards, o driver se conecta a todas as trinta instâncias mongos por padrão. Você pode usar a opção srvMaxHosts na sua string de conexão para definir o número máximo de hosts aos quais o driver se conecta. Para melhorar o desempenho do driver, defina srvMaxHosts=3. Por exemplo:

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

    Para saber mais, consulte Opções de conexão.

  • Restringir o acesso à rede ao seu Atlas cluster.

    Conecte-se ao cluster do Atlas por meio de rede privada usando uma conexão de peering rede entre o cluster do Atlas e a função do AWS Lambda ou, alternativamente, um endpoint privado, para que você possa permitir apenas endereços IP privados da sua lista de acesso IP.

    Se você não usa redes privadas, considere conectar-se ao seu cluster do Atlas por meio de um gateway NAT com um endereço IP elástico mapeado. Caso contrário, você deve permitir que todos os endereços IP (0.0.0.0/0) acessem seu cluster de serviços.

    Aviso

    Adicionar 0.0.0.0/0 à sua lista de acesso IP permite o acesso ao cluster de qualquer lugar na Internet pública. Certifique-se de usar credenciais fortes para todos os utilizadores de banco de dados ao permitir o acesso de qualquer lugar.

  • Defina maxIdleTimeMS como 60000 para fechar automaticamente suas conexões após 1 minuto de tempo ocioso. Ajustar seu maxIdleTimeMS pode ajudar a reduzir a ocorrência de erros de tempo limite nas suas funções sem servidor.

  • Configure o AWS Access unificado e use a autenticação IAM do AWS sempre que possível.

    Você pode se conectar aos clusters do Atlas usando AWS funções IAM em vez de codificar suas credenciais no Lambda. As credenciais codificadas podem ser visualizadas por qualquer pessoa que acesse seu ambiente do AWS Lambda, o que pode representar um risco à segurança. Com a autenticação do AWS IAM, o Atlas acessa o AWS Lambda por meio de uma função presumida do IAM, então você não precisa de credenciais em suas cadeias de conexão.

    O Atlas permite a autenticação do AWS IAM para clusters que executam o MongoDB versão 5.0 ou superior. É altamente recomendável usar a autenticação do AWS IAM para conexões Lambda se o seu cluster atender aos requisitos.

  • A quantidade de memória alocada para uma função Lambda é padronizada para 128 MB. Você pode configurar a quantidade de memória alocada para uma função Lambda, entre 128 MB e 10.240 MB. Certifique-se de alocar memória suficiente. Aumente a memória para aumentar a quantidade de CPU virtual disponível e melhorar o desempenho do driver do MongoDB. Para saber mais, consulte Memória e potência de computação.

  • Defina suas variáveis de ambiente AWS_STS_REGIONAL_ENDPOINTS e 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(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(())
}