MongoDB C # Драйвер не освобождает соединения, ошибки - PullRequest
2 голосов
/ 16 сентября 2011

Я использую последние версии MongoDB (на сервере Win 64) и драйвер C #. У меня есть служба Windows, которая выполняет 800 операций чтения и обновления в минуту, и через несколько минут текущие используемые потоки превышают 200, а затем каждый отдельный вызов mongodb выдает эту ошибку:

System.IO.IOException: Unable to read data from the transport connection: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. ---> System.Net.Sockets.SocketException: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond
   at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)
   at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)

У меня есть индекс по полям, которые читаются, поэтому проблема не в этом. Вот код для чтения:

public static UserUpdateMongo Find(int userId, long deviceId)
{
    return Collection().Find(
        Query.And(
            Query.EQ("UserId", userId),
            Query.EQ("DeviceId", deviceId))).FirstOrDefault();
}

Я инстанцирую соединение так:

var settings = new MongoServerSettings
{
    Server = new MongoServerAddress(segments[0], Convert.ToInt32(segments[1])),MaxConnectionPoolSize = 1000};
    Server = MongoServer.Create(settings);
}

Я что-то не так делаю или есть проблема с драйвером C #? Помогите !!

Ответы [ 3 ]

4 голосов
/ 17 сентября 2011

Драйвер C # имеет пул соединений, а максимальный размер пула соединений по умолчанию равен 100.Поэтому вы никогда не должны видеть более 100 подключений к mongod из одного клиентского процесса C #.В версии 1.1 для драйвера C # иногда возникала проблема при большой нагрузке, когда ошибка в одном соединении могла привести к серии отключений и подключений.Вы сможете определить, происходило ли это с вами, просмотрев журналы сервера, где запись журнала записывается каждый раз, когда соединение открывается или закрывается.Если да, можете ли вы попробовать драйвер 1.2 C #, выпущенный на этой неделе?

Вам не нужно было создавать очередь ожидающих обновлений.Пул подключений действует как своего рода очередь, ограничивая количество одновременных запросов.

Дайте мне знать, если вы можете найти что-либо в журналах сервера, и если что-то еще будет, я могу вам помочь.

2 голосов
/ 17 сентября 2011

Решением было прекратить сохранение записей в каждом отдельном потоке и начать добавлять их в список «ожидающих сохранения» в памяти.Затем создайте отдельный поток, который синхронно обрабатывает все сохранения в mongodb.Я не знаю, почему асинхронные вызовы приводят к отключению драйвера C #, но теперь это работает прекрасно.Вот пример кода, если другие сталкиваются с этой проблемой:

public static class UserUpdateSaver
    {
        public static List<UserUpdateView> PendingUserUpdates;

        public static void Initialize()
        {
            PendingUserUpdates = new List<UserUpdateView>();
            var saveUserUpdatesTime = Convert.ToInt32(ConfigurationBL.ReadApplicationValue("SaveUserUpdatesTime"));
            LogWriter.Write("Setting up timer to save user updates every " + saveUserUpdatesTime + " seconds", LoggingEnums.LogEntryType.Warning);
            var worker = new BackgroundWorker();
            worker.DoWork += delegate(object s, DoWorkEventArgs args)
            {
                while (true)
                {//process pending user updates every x seconds.
                    Thread.Sleep(saveUserUpdatesTime * 1000);
                    ProcessPendingUserUpdates();
                }
            };
            worker.RunWorkerAsync();
        }

        public static void AddUserUpdateToSave(UserUpdateView userUpdate)
        {
            Monitor.Enter(PendingUserUpdates);
            PendingUserUpdates.Add(userUpdate);
            Monitor.Exit(PendingUserUpdates);
        }

        private static void ProcessPendingUserUpdates()
        {
            //get pending user updates.
            var pendingUserUpdates = new List<UserUpdateView>(PendingUserUpdates);
            if (pendingUserUpdates.Count > 0)
            {
                var startDate = DateTime.Now;

                foreach (var userUpdate in pendingUserUpdates)
                {
                    try
                    {
                        UserUpdateStore.Update(userUpdate);
                    }
                    catch (Exception exc)
                    {
                        LogWriter.WriteError(exc);
                    }
                    finally
                    {
                        Monitor.Enter(PendingUserUpdates);
                        PendingUserUpdates.Remove(userUpdate);
                        Monitor.Exit(PendingUserUpdates);
                    }
                }

                var duration = DateTime.Now.Subtract(startDate);
                LogWriter.Write(String.Format("Processed {0} user updates in {1} seconds",
                    pendingUserUpdates.Count, duration.TotalSeconds), LoggingEnums.LogEntryType.Warning);
            }
            else
            {
                LogWriter.Write("No user updates to process", LoggingEnums.LogEntryType.Warning);
            }
        }
    }
0 голосов
/ 23 марта 2012

Вы слышали о очереди сообщений? Вы можете поместить несколько блоков для обработки такой нагрузки и использовать механизм очереди сообщений для сохранения ваших данных в mongodb. Но в этом случае ваша очередь сообщений должна быть в состоянии выполнить одновременную публикацию подписки. Бесплатная очередь сообщений (на мой взгляд, очень хорошая) - MassTransit с RabbitMQ.

Рабочий процесс будет: 1. Опубликуйте свои данные в очереди сообщений; 2. Когда он появится, запустите с подписчиками столько ящиков, сколько вам нужно, чтобы сохранить и обработать ваши данные монго.

Этот подход будет хорош, если вам нужно масштабировать.

...