Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How should the lifecycle of MongoClient work?

I have an ASP.Net MVC application using MongoDB as the database. The website and the database are on separate servers.

At the moment, I have a class that looks like this:

public class Mongo
{
    private IMongoDatabase database;

    public Mongo()
    {
        var client = new MongoClient("mongodb://username:password@ipaddress:port");
        database = client.GetDatabase("MyDatabase");
    }

    public IMongoCollection<ApplicationUser> Users() { return database.GetCollection<ApplicationUser>("Users"); }
}

So to use it... (essentially in every request)

Mongo mon = new Mongo();
mon.Users.Find(........); // etc.

And this works ok - most of the time. On the odd occasion things appear to lock up and the database just times out until I restart the website. I get timeout errors where it's trying to connect to the database server.

While that's going on, the database server is confirmed up, and I'm able to connect to MongoDB from another mongo client without issue.

I'm conscious that there's no "close connection" thing going on in this - but there doesn't appear to be one to even call. So I wonder if it's something to do with too many connections being open and not being cleaned up properly.

Am I using MongoClient incorrectly? Is there something obvious that I should be doing to stop these timeouts?

This is the trace of the error I get:

   [SocketException (0x274c): A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond ipaddress:port]
       System.Net.Sockets.Socket.EndConnect(IAsyncResult asyncResult) +6768957
       System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization) +57
       System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +99
       System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +58
       System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task) +25
       MongoDB.Driver.Core.Connections.<ConnectAsync>d__7.MoveNext() +1542
       System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +99
       System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +58
       MongoDB.Driver.Core.Connections.<CreateStreamAsync>d__0.MoveNext() +345
       System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +99
       System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +58
       MongoDB.Driver.Core.Connections.<OpenAsyncHelper>d__1.MoveNext() +553

[MongoConnectionException: An exception occurred while opening a connection to the server.]
   MongoDB.Driver.Core.Connections.<OpenAsyncHelper>d__1.MoveNext() +1372
   System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +99
   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +58
   MongoDB.Driver.Core.Servers.<GetChannelAsync>d__0.MoveNext() +548
   System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +99
   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +58
   System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task) +25
   MongoDB.Driver.Core.Operations.<ExecuteAsync>d__2.MoveNext() +639
   System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +99
   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +58
   MongoDB.Driver.<ExecuteReadOperationAsync>d__0`1.MoveNext() +272
   System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +99
   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +58
   MongoDB.Driver.<ExecuteReadOperation>d__35`1.MoveNext() +396
   System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +99
   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +58
   MongoDB.Driver.<ToListAsync>d__14`1.MoveNext() +294
like image 975
Paul Avatar asked Oct 09 '15 14:10

Paul


People also ask

Do I need to close MongoClient?

Of course, you should close the MongoClient instance, with the close() method (I had mentioned in my previous reply) at the closing of the application, to clear all the resources. This note is about using the code for creating the MongoClient object and its close() method.

Should MongoClient be Singleton?

Typically yes, it is a good practice to make MongoClient a singleton.

What is the use of MongoClient?

The MongoClient class is a class that allows for making Connections to MongoDB. The programmatically provided options take precedence over the URI options.

How does MongoDB connection pool work?

A connection pool is a cache of open, ready-to-use database connections maintained by the driver. Your application can seamlessly get connections from the pool, perform operations, and return connections back to the pool. Connection pools are thread-safe.


1 Answers

You are using MongoClient incorrectly. As indicated in the docs

It is recommended to store a MongoClient instance in a global place, either as a static variable or in an IoC container with a singleton lifetime.

So you should rework your code to create a singleton MongoClient instance and then use that throughout your program.

The reason is that MongoClient maintains a pool of open connections that can be shared and reused for best performance.

like image 97
JohnnyHK Avatar answered Oct 06 '22 02:10

JohnnyHK