Подтвердить что ты не робот

.NET лучшие практики для соединений MongoDB?

Недавно я играл с MongoDB (это удивительно FAST), используя драйвер С# на 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);
        }
    }
}
4b9b3361

Ответ 1

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

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

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

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

Ответ 2

Вещь, которую следует помнить о статическом соединении, заключается в том, что она разделялась между всеми вашими потоками. То, что вы хотите, - это одно соединение на поток.

Ответ 3

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

Пример

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

Журнал базы данных
Ср Июн 02 20:54:21 Связь принята с 127.0.0.1:58214 # 1
Ср Июн 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

Ответ 4

Немного, но все же интересный CSMongo, - драйвер С# для 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);

}

Ответ 5

Пул соединений должен быть вашим ответом.

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

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

Я не знаю недостатка в использовании объекта Global Mongo. Поэтому позвольте подождать еще одного эксперта, чтобы прокомментировать это.

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

Ответ 6

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

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

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

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