Я играл с MongoDB недавно (Это - УДИВИТЕЛЬНО FAST), использование драйвера C# на GitHub. Все работает просто великолепно в моем небольшом единственном потоковом консольном приложении, с которым я тестирую. Я могу добавить, что 1 000 000 документов (да, миллион) за менее чем 8 секунд, работая единственный распараллелили. Я только получаю эту производительность, если я использую соединение вне объема для цикла. Другими словами, я сохраняю соединение открытым для каждого, вставляют вместо того, чтобы соединиться для каждого, вставляют. Очевидно, это изобретено.
Я думал, что проверну его на ступеньку выше, чтобы видеть, как это работает с несколькими потоками. Я делаю это, потому что я должен моделировать веб-сайт с несколькими параллельными запросами. Я вращаюсь между 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);
}
}
}
Что нужно помнить о статическом соединении, так это то, что оно используется всеми вашими потоками. Вам нужно одно соединение на поток.
Несколько, но все же представляет интерес 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);
}
Пул подключений должен быть вашим ответом.
Функция находится в стадии разработки (подробнее см. http://jira.mongodb.org/browse/CSHARP-9 ).
Прямо сейчас для веб-приложения лучше всего подключиться по BeginRequest и освободить соединение по EndRequest. Но мне кажется, что операция обходится слишком дорого для каждого запроса без пула соединений. Поэтому я решил создать глобальный объект Mongo и использовать его в качестве общего ресурса для всех потоков (если вы прямо сейчас получите последнюю версию драйвера C # из github, они также немного улучшат производительность для параллелизма).
Я не знаю недостатков использования объекта Global Mongo. Так что подождем, пока это прокомментирует другой эксперт.
Но я думаю, что смогу жить с этим, пока функция (пул соединений) не будет завершена.