Poklakni
Poklakni

Reputation: 351

Connecting to MongoDB Atlas from AWS Lambda takes too long

The cold start takes approx. 10 seconds which is unacceptable for me. If lambda reuses the connection, the duration decreases to 30ms. Is there any way how to improve initial connection time?

The most time-consuming part (6 seconds)

2020-08-04T20:39:45.004+02:00 INFO: No server chosen by com.mongodb.client.internal.MongoClientDelegate from cluster description ClusterDescription{type=REPLICA_SET, connectionMode=MULTIPLE, serverDescriptions=[ServerDescription{, type=UNKNOWN, state=CONNECTING}, ServerDescription{, type=UNKNOWN, state=CONNECTING}, ServerDescription{, type=UNKNOWN, state=CONNECTING}]}. Waiting for 30000 ms before timing out

2020-08-04T20:39:51.302+02:00 Aug 04, 2020 6:39:51 PM com.mongodb.diagnostics.logging.JULLogger log

import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;

import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;

public class MongoDBConnectionLambdaHandler implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {

    // declare MongoClient as an instance variable to ensure connection pooling
    private MongoClient mongoClient = null;

    @Override
    public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent request, Context context) {

        MongoDatabase database = getDBConnection(context);

        APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent();
        Document doc = database.getCollection(System.getenv("MONGO_DB_COLLECTION"))
                               .find()
                               .first();

        response.setBody(doc == null ? null : doc.toJson());

        response.setStatusCode(200);
        return response;
    }

    private MongoDatabase getDBConnection(Context context) {

        if (mongoClient == null) {

            context.getLogger().log("Initializing new MongoDB connection");
            mongoClient = MongoClients.create(System.getenv("MONGO_DB_URI"));
            return mongoClient.getDatabase(System.getenv("MONGO_DB_NAME"));
        }

        context.getLogger().log("Reusing existing MongoDB connection");
        return mongoClient.getDatabase(System.getenv("MONGO_DB_NAME"));
    }

}

Upvotes: 1

Views: 990

Answers (1)

Poklakni
Poklakni

Reputation: 351

I managed to cut down the initial connection time by 2 seconds by triggering a connection outside the handler method. The remaining time is probably a result of language choice.

import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;

import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;

import org.bson.Document;

public class MongoDBConnectionHandler implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {

    // declare MongoClient as an instance variable to ensure connection pooling
    private final MongoClient mongoClient = MongoClients.create(System.getenv("MONGO_DB_URI"));

    @Override
    public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent request, Context context) {

        APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent();
        Document doc = mongoClient.getDatabase(System.getenv("MONGO_DB_NAME"))
                                  .getCollection(System.getenv("MONGO_DB_COLLECTION"))
                                  .find()
                                  .first();

        response.setBody(doc == null ? null : doc.toJson());

        response.setStatusCode(200);
        return response;
    }

}

Upvotes: 1

Related Questions