.NET最佳实践的MongoDB连接?
我一直在使用GitHub上的C#驱动程序来玩MongoDB(它的速度惊人)。 在我testing的小型单线程控制台应用程序中,一切正常。 我能够在8秒内添加100万个文件(是的,百万)运行单线程。 如果我使用for循环范围之外的连接,我只会得到这个性能。 换句话说,我保持每个插入连接而不是连接每个插入。 显然这是人为的。
我以为我会对它进行一番调查,看看它是如何与多个线程一起工作的。 我这样做是因为我需要模拟一个有多个并发请求的网站。 我正在旋转15到50个线程,在所有情况下总共插入了15万个文件。 如果我只是让线程运行,每个插入操作创build一个新的连接,性能就会停下来。
显然,我需要find一种方法来共享,locking或合并连接。 这就是问题所在。 连接到MongoDB的最佳做法是什么? 连接应该在应用程序的整个生命周期内保持打开状态(每个操作的TCP连接都有大量的延迟打开和closures)?
有没有人有任何真实的世界或MongoDB生产经验,特别是底层的连接?
这是我的线程示例使用一个静态连接,被locking插入操作。 请提供build议,以最大限度地提高networking环境中的性能和可靠性!
private static Mongo _mongo; private static void RunMongoThreaded() { _mongo = new Mongo(); _mongo.Connect(); var threadFinishEvents = new List<EventWaitHandle>(); for(var i = 0; i < 50; i++) { var threadFinish = new EventWaitHandle(false, EventResetMode.ManualReset); threadFinishEvents.Add(threadFinish); var thread = new Thread(delegate() { RunMongoThread(); threadFinish.Set(); }); thread.Start(); } WaitHandle.WaitAll(threadFinishEvents.ToArray()); _mongo.Disconnect(); } private static void RunMongoThread() { for (var i = 0; i < 3000; i++) { var db = _mongo.getDB("Sample"); var collection = db.GetCollection("Users"); var user = GetUser(i); var document = new Document(); document["FirstName"] = user.FirstName; document["LastName"] = user.LastName; lock (_mongo) // Lock the connection - not ideal for threading, but safe and seemingly fast { collection.Insert(document); } } }
这里的大多数答案已经过时 ,并且不再适用,因为.net驱动程序已经成熟,并添加了无数的function。
看看在这里find新的2.0驱动程序的文档: http : //mongodb.github.io/mongo-csharp-driver/2.0/reference/driver/connecting/
.net驱动程序现在是线程安全的并处理连接池。 根据文件
build议将MongoClient实例存储在一个全局的地方,作为一个静态variables或者在一个具有单例生命周期的IoC容器中。
关于一个静态连接要记住的是它是在你的所有线程中共享的。 你想要的是每个线程一个连接。
当使用mongodb-csharp时,你会像ADO连接一样对待它。 当你创build一个Mongo对象的时候,它会从它所拥有的池中借用一个连接,直到它被丢弃。 所以在使用块之后,连接回到池中。 创buildMongo对象既便宜又快速。
例
for(var i=0;i<100;i++) { using(var mongo1 = new Mongo()) using(var mongo2 = new Mongo()) { mongo1.Connect(); mongo2.Connect(); } }
数据库日志
Wed Jun 02 20:54:21连接从127.0.0.1:58214#1接受
Wed Jun 02 20:54:21连接从127.0.0.1:58215#2接受
Wed Jun 02 20:54:21 MessagingPort recv()errno:0没有错误127.0.0.1:58214
Wed Jun 02 20:54:21 end connection 127.0.0.1:58214
Wed Jun 02 20:54:21 MessagingPort recv()errno:0没有错误127.0.0.1:58215
Wed Jun 02 20:54:21 end connection 127.0.0.1:58215
注意它只打开了2个连接。
我把这个使用mongodb-csharp论坛。 http://groups.google.com/group/mongodb-csharp/browse_thread/thread/867fa78d726b1d4
CSMongo是一个由jLinq开发者创build的用于MongoDB的C#驱动程序。 这是一个示例:
//create a database instance using (MongoDatabase database = new MongoDatabase(connectionString)) { //create a new document to add MongoDocument document = new MongoDocument(new { name = "Hugo", age = 30, admin = false }); //create entire objects with anonymous types document += new { admin = true, website = "http://www.hugoware.net", settings = new { color = "orange", highlight = "yellow", background = "abstract.jpg" } }; //remove fields entirely document -= "languages"; document -= new[] { "website", "settings.highlight" }; //or even attach other documents MongoDocument stuff = new MongoDocument(new { computers = new [] { "Dell XPS", "Sony VAIO", "Macbook Pro" } }); document += stuff; //insert the document immediately database.Insert("users", document); }
连接池应该是你的答案。
该function正在开发中(请参阅http://jira.mongodb.org/browse/CSHARP-9了解更多详情)。;
现在,对于Web应用程序,最好的做法是在BeginRequest处连接并在EndRequest处释放连接。 但是对于我来说,我认为对于没有连接池的每个请求来说操作太昂贵了。 所以我决定拥有全局的Mongo对象,并把它作为每个线程的共享资源(如果你现在从github获得最新的C#驱动,它们也会提高并发性)。
我不知道使用Global Mongo对象的缺点。 所以让我们等待另一位专家对此发表评论。
但是我想我可以忍受它,直到function(连接池)完成。
我正在使用csharp-mongodb驱动程序,并没有帮助我与他的连接池:(我有约10-20请求mongodb每个Web请求(150用户在线 – 平均)而我什至不能监控统计或连接从shellmongodb它抛出exception给我。
我创build了存储库,根据请求打开并处理连接。 我依靠这样的事情:1)驱动程序有连接池2)经过我的研究(我在用户组中发布了一些关于此的问题) – 我明白创buildmongo对象和打开连接不会重操作,所以操作繁重。
但今天我的生产下降:(可能我必须保存每个请求打开连接…
这里是链接到用户组http://groups.google.com/group/mongodb-user/browse_thread/thread/3d4a4e6c5eb48be3#