首页 文章

MongoDB连接的.NET最佳实践?

提问于
浏览
54

我最近一直在使用GitHub上的C#驱动程序玩MongoDB(它的速度非常快) . 在我正在测试的小单线程控制台应用程序中,一切正常 . 我可以在8秒内运行单线程添加1,000,000个文档(是的,百万个) . 如果我使用for循环范围之外的连接,我只能获得此性能 . 换句话说,我保持每个插入的连接打开,而不是连接每个插入 . 显然这是做作的 .

我以为我会把它调到一个档位,看它是如何与多线程一起工作的 . 我这样做是因为我需要模拟一个包含多个并发请求的网站 . 我在15到50个线程之间旋转,在所有情况下仍然插入总共150,000个文档 . 如果我让线程运行,每个线程为每个插入操作创建一个新连接,性能就会停止 .

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

有没有人有MongoDB的任何现实世界或 生产环境 经验,特别是底层连接?

这是我使用为插入操作锁定的静态连接的线程示例 . 请提供可在Web环境中最大限度地提高性能和可靠性的建议!

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);
        }
    }
}

6 回答

  • 6

    Most answers here are outdated 并且不再适用,因为.net驱动程序已经成熟并且添加了无数功能 .

    查看此处的新2.0驱动程序的文档:http://mongodb.github.io/mongo-csharp-driver/2.0/reference/driver/connecting/

    .net驱动程序现在是线程安全的并处理连接池 . 根据文件

    建议将MongoClient实例存储在全局位置,可以是静态变量,也可以是具有单例生存期的IoC容器 .

  • 1

    关于静态连接要记住的是它在所有线程之间共享 . 你想要的是每个线程一个连接 .

  • 9

    使用mongodb-csharp时,您会像处理ADO连接一样对待它 . 当你创建一个Mongo对象时,它借用了池所拥有的连接,直到它被处置为止 . 因此,在使用块之后,连接将重新进入池中 . 创建Mongo对象既便宜又快捷 .

    Example

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

    Database Log
    2月2日星期三20:54:21从127.0.0.1:58214#1接受连接
    2月2日星期三20:54:21从127.0.0.1:58215#2接受连接
    Wed Jun 02 20:54:21 MessagingPort recv()错误号码: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()错误号码: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

  • 72

    有点但仍然感兴趣的是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);
    
    }
    
  • 0

    连接池应该是你的答案 .

    该功能正在开发中(有关详细信息,请参阅http://jira.mongodb.org/browse/CSHARP-9) .

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

    我不知道使用Global Mongo对象的缺点 . 所以让我们等待另一位专家对此发表评论 .

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

  • 0

    我正在使用csharp-mongodb驱动程序,它没有帮助我他的连接池:(我有大约10-20请求mongodb每个网络请求 . (150用户在线 - 平均)我甚至无法监控统计或连接来自shell的mongodb它给我带来了异常 .

    我创建了存储库,它根据请求打开并处理连接 . 我依赖于以下内容:1)驱动程序有连接池2)经过我的研究(我已经在用户组中发布了一些关于此的问题) - 我明白创建mongo对象和打开连接不会操作繁重,操作繁重 .

    但今天我的作品下降了:(可能是我必须保存每个请求的开放连接...

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

相关问题