.NET 对 MongoDB 连接的最佳实践?

我最近一直在使用 GitHub 上的 C # 驱动程序来玩 MongoDB (它的速度令人惊讶地快)。在我正在测试的单线程控制台应用程序中,一切都运行良好。我可以在8秒内运行单线程添加1,000,000个文档(是的,100万)。只有在使用 for 循环范围之外的连接时,才能获得这种性能。换句话说,我为每个插入保持连接打开,而不是为每个插入进行连接。显然这是人为的。

我想我应该把它提高一个档次,看看它是如何与多个线程一起工作的。我这样做是因为我需要模拟一个具有多个并发请求的网站。我将旋转15到50个线程,仍然在所有情况下总共插入150,000个文档。如果我只是让线程运行,每个线程为每个插入操作创建一个新的连接,那么性能就会陷入停顿。

显然,我需要找到一种方法来共享、锁定或池连接。这就是问题所在。连接 MongoDB 的最佳实践是什么?连接是否应该在应用程序的生命周期内保持打开状态(每次操作都有大量的开启和关闭 TCP 连接的延迟) ?

是否有人具有任何使用 MongoDB 的真实世界或生产经验,特别是底层连接?

下面是使用静态连接的线程示例,该连接为插入操作锁定。请提供建议,将最大限度地提高性能和可靠性在网络上下文!

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);
}
}
}
35793 次浏览

关于静态连接,需要记住的一点是,它是在所有线程之间共享的。您需要的是每个线程一个连接。

连接池应该是您的答案。

该功能正在开发中(请参阅 http://jira.mongodb.org/browse/CSHARP-9了解更多细节)。

现在,对于 Web 应用程序,最佳实践是在 BeginRequest 连接,并在 EndRequest 释放连接。但是对于我来说,我认为对于没有连接池的每个请求来说,这个操作都太昂贵了。因此,我决定使用全局 Mongo 对象,并将其作为每个线程的共享资源(如果您现在从 github 获得最新的 C # 驱动程序,它们也会稍微提高并发性能)。

我不知道使用 GlobalMongo 对象的缺点,所以让我们等待另一位专家对此进行评论。

但我认为我可以忍受它,直到功能(连接池)已经完成。

有点但仍然感兴趣的是 CSMongo,,它是由 jLinq 开发人员创建的 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);


}

当使用 mongodb-cSharp 时,就像对待 ADO 连接一样对待它。 当您创建一个 Mongo 对象时,它从池中借用一个连接,直到它被释放为止。因此,在 using 块之后,连接将返回到池中。 创建 Mongo 对象既便宜又快捷。

例子

for(var i=0;i<100;i++)
{
using(var mongo1 = new Mongo())
using(var mongo2 = new Mongo())
{
mongo1.Connect();
mongo2.Connect();
}
}

数据库日志
星期三6月2日20:54:21接受来自127.0。0.1:58214 # 1
星期三6月2日20:54:21接受来自127.0。0.1:58215 # 2
6月2日星期三20:54:21 MessagingPort recv () errno: 0 No error 127.0.0.1:58214
星期三6月2日20:54:21结束连接127.0.0.1:58214
6月2日星期三20:54:21 MessagingPort recv () errno: 0 No error 127.0.0.1:58215
星期三6月2日20:54:21结束连接127.0.0.1:58215

注意它只打开了2个连接。

我用 mongodb-c Sharp 论坛组装的。 Http://groups.google.com/group/mongodb-csharp/browse_thread/thread/867fa78d726b1d4

我使用的是 cSharp-mongodb 驱动程序,它不能帮助我处理他的连接池: (每个 web 请求我有10-20个 mongodb 请求。(150个用户在线平均)我甚至不能监视统计数据或者从 shell 连接到 mongodb 它会抛出异常给我。

我已经创建了存储库,它根据每个请求打开和释放连接: 1)驱动程序有连接池 2)经过我的研究(我已经张贴了一些问题在用户组关于这一点)-我知道创建 mongo 对象和开放连接不繁重的操作,所以繁重的操作。

但是今天我的产量下降了 也许我必须保存每个请求打开连接..。

这里是到用户组 http://groups.google.com/group/mongodb-user/browse_thread/thread/3d4a4e6c5eb48be3#的链接

这里的大多数答案已经过时了 ,不再适用于。网络驱动程序已经成熟,增加了无数的功能。

在这里查看新的2.0驱动程序的文档: Http://mongodb.github.io/mongo-csharp-driver/2.0/reference/driver/connecting/

Net 驱动程序现在是线程安全的,可以处理连接池

建议将 MongoClient 实例存储在全局位置,或者作为静态变量,或者存储在具有单例生存期的 IoC 容器中。