.NET лучшие практики для подключений MongoDB? - PullRequest
58 голосов
/ 03 февраля 2010

Я недавно играл с MongoDB (это ИЗУМИТЕЛЬНО БЫСТРО), используя драйвер C # на GitHub. Все отлично работает в моем маленьком однопоточном консольном приложении, с которым я тестирую. Я могу добавить 1 000 000 документов (да, миллион) менее чем за 8 секунд, работая однопоточным. Я получаю эту производительность только в том случае, если я использую соединение за пределами цикла 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);
        }
    }
}

Ответы [ 6 ]

92 голосов
/ 12 июня 2015

Большинство ответов здесь устарели и больше не применимы, поскольку драйвер .net созрел и добавил бесчисленные функции.

Посмотрите документацию нового драйвера 2.0, найденную здесь:http://mongodb.github.io/mongo-csharp-driver/2.0/reference/driver/connecting/

Драйвер .net теперь является потокобезопасным и обрабатывает пулы соединений.В соответствии с документацией

Рекомендуется хранить экземпляр MongoClient в глобальном месте, либо в виде статической переменной, либо в контейнере IoC с одиночным временем жизни.

9 голосов
/ 03 февраля 2010

Помните, что статическое соединение является общим для всех ваших потоков. То, что вы хотите, это одно соединение на поток.

5 голосов
/ 05 ноября 2010

При использовании mongodb-csharp вы относитесь к нему так же, как к ADO-соединению.Когда вы создаете объект Mongo, он заимствует соединение из пула, которым он владеет, пока не будет удален.Таким образом, после использования блока соединение возвращается в пул.Создание монго объектов дешево и быстро.

Пример

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

База данных Log Ср Июн 02 20:54:21 соединение принято от 127.0.0.1:58214 # 1Ср Июн 02 20:54:21 соединение принято от 127.0.0.1:58215 # 2Ср Июн 02 20:54:21 MessagingPort recv () errno: 0 Нет ошибок 127.0.0.1:58214Ср Июн 02 20:54:21 конец соединения 127.0.0.1:58214Ср Июн 02 20:54:21 MessagingPort recv () errno: 0 Нет ошибок 127.0.0.1:58215Ср Июн 02 20:54:21 конец соединения 127.0.0.1:58215

Обратите внимание, что было открыто только 2 соединения.

Я собрал все это, используя форум mongodb-csharphttp://groups.google.com/group/mongodb-csharp/browse_thread/thread/867fa78d726b1d4

1 голос
/ 07 марта 2010

Немного, но все еще представляет интерес CSMongo, драйвер C # для MongoDB, созданный разработчиком jLinq. Вот образец:

//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 голосов
/ 09 декабря 2010

Я использую драйвер csharp-mongodb, и он не помогает мне с его пулом соединений :( У меня около 10-20 запросов на mongodb на веб-запрос. (150 пользователей онлайн - в среднем) И я даже не могу контролировать Статистика или подключиться к mongodb из оболочки это исключение для меня.

Я создал репозиторий, который открывает и удаляет соединение по запросу. Я полагаюсь на такие вещи, как: 1) Драйвер имеет пул подключений 2) После моего исследования (я написал об этом несколько групп пользователей) - я понял, что создание объекта монго и открытого соединения не тяжелая операция, поэтому тяжелая операция.

Но сегодня мое производство остановилось :( Может быть, мне нужно сохранить открытое соединение по запросу ...

здесь ссылка на группу пользователей http://groups.google.com/group/mongodb-user/browse_thread/thread/3d4a4e6c5eb48be3#

0 голосов
/ 07 марта 2010

Connection Pool должен быть вашим ответом.

Эта функция разрабатывается (см. http://jira.mongodb.org/browse/CSHARP-9 для более подробной информации).

Прямо сейчас, для веб-приложения, лучшийПрактика состоит в том, чтобы соединиться в BeginRequest и освободить соединение в EndRequest.Но мне кажется, что операция слишком дорогая для каждого запроса без пула соединений.Поэтому я решил использовать глобальный объект Mongo и использовать его в качестве общего ресурса для всех потоков (если вы прямо сейчас получаете последнюю версию драйвера C # от github, они также немного улучшают производительность для параллелизма).Не знаю недостаток использования объекта Global Mongo.Так что давайте подождем, пока другой эксперт прокомментирует это.

Но я думаю, что смогу жить с этим, пока функция (пул подключений) не будет завершена.

...