[CSHARP-1290] MongoClient Connection Pooling Created: 21/May/15 Updated: 05/Apr/19 Resolved: 22/May/15 |
|
| Status: | Closed |
| Project: | C# Driver |
| Component/s: | Connectivity |
| Affects Version/s: | 2.0 |
| Fix Version/s: | None |
| Type: | Task | Priority: | Major - P3 |
| Reporter: | Peter Gordon | Assignee: | Unassigned |
| Resolution: | Done | Votes: | 0 |
| Labels: | question | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original Estimate: | Not Specified | ||
| Environment: |
ASP.NET MVC 5 with Mongo on Windows Server 2012 (test server) |
||
| Issue Links: |
|
||||||||
| Description |
|
What's the best practice for ensuring that the connection pool works properly with version 2.0 and async requests. I have a prototype application built using the new driver that creates a new MongoClient object on each request. The app is not using a connection string, rather it is building a MongoClientSettings object and using that when creating the MongoClient. Under load, my app creates an enormous number of connections to Mongo causing me to have to increase the maximum pool size and, as a result, it uses too many resources and bogs down fairly quickly. Does the new driver use the same pool if I create a new MongoClient with the same settings set on the constructor or does it use a separate pool for each MongoClient object? I am trying to determine if I need to store the connection at the application level vs. per request (which normally I would do anyway) or if the problem is related to the async processes. |
| Comments |
| Comment by Craig Wilson [ 22/May/15 ] |
|
Hi Peter, I was wrong. Removing the reference will not work. We currently don't offer a way to shut down a cluster. I've created Thanks for the report and the questions, |
| Comment by Craig Wilson [ 22/May/15 ] |
|
We don't currently offer a way to dispose of that thing. However, if you remove the reference, they'll get cleaned up by the GC eventually. |
| Comment by Peter Gordon [ 21/May/15 ] |
|
Craig - one last question on this - if I store a list of MongoClients in the application, is there a way in the API to dispose of connections properly ... I.e if I determine that a given client has not been used in a certain amount of time - or should I just remove the MongoClient and rely on garbage collection. |
| Comment by Peter Gordon [ 21/May/15 ] |
|
Sounds good - thanks for the quick response. |
| Comment by Craig Wilson [ 21/May/15 ] |
|
Yes, different credentials can also cause problems because we store them securely. Your best bet, in a system like this, is still to use Singletons. You can store them globally somewhere in a dictionary. You know best about what should be the same in your system. That's my advice. |
| Comment by Peter Gordon [ 21/May/15 ] |
|
Yes - I mean different servers. For instance, our dev team can use the UI to connect to their personal dev server, our test servers, or in some cases our production servers. |
| Comment by Peter Gordon [ 21/May/15 ] |
|
Craig - is it also possible that the system cannot compare the Credentials other than a referential equality? I removed the ClusterConfigurator and the error still occurs and the only other setting other than server name on the connection is I am manually creating the client credential (MongoCredential.CreateCredential) on each one. |
| Comment by Craig Wilson [ 21/May/15 ] |
|
In theory, if your ClusterConfigurator was a defined method somewhere and you didn't use a lambda expression for it, then it should compare equally. Regardless, I think it'd be best to manage them in a ConcurrentDictionary somewhere anyways. When you say different database... do you mean different servers? |
| Comment by Peter Gordon [ 21/May/15 ] |
|
One thought - if I create a singleton ClusterConfigurator, would I then be safe to create a connection on each request provided I use the same referenced ClusterConfigurator on each MongoClient? |
| Comment by Peter Gordon [ 21/May/15 ] |
|
My prototype app includes a small web based Mongo admin utility which allows you to create connections to different databases and run queries, inserts, etc... against that database. As a result, each user could be working on a different connection. The problem is likely related to the ClusterConfigurator as I am using that to set the serverSelectionTimeout to something less than the default 30 seconds. I'll remove that and see if that is the root cause of the problem. Sounds like I'll have to refactor it so that it stores a MongoClient object either per session or a thread safe list of them on the application in some fashion. |
| Comment by Craig Wilson [ 21/May/15 ] |
|
The driver will, for the most part, use the same connection settings. However, certain connection settings cannot be compared (like ClusterConfigurator which is a delegate and can only be compared for referential equality, not content). Hence, the best practice will be to only instantiate 1 MongoClient at app startup and use that. Put it in an IoC container, create a static variable somewhere, etc... Essentially, make it a singleton. Is there any reason you are constructing a new client for every request? Craig |