Чтение из MSMQ замедляется, когда в очереди много сообщений

Краткое введение

У меня есть система на основе SEDA, и я использовал MSMQ для связи (запуск событий) между различными приложениями / службами .

Одна из этих служб получает сообщения по файлам, поэтому у меня есть прослушиватель файлов, который читает содержимое файла и в помещает это в очередь (или на самом деле 4 разные очереди, но это не очень важно для первого вопроса).

Сервер - Windows Server 2008

Первый вопрос - чтение замедляется

Мое приложение, которое читает эти сообщения на другой стороне, обычно читает около 20 сообщений из очереди в секунду,но когда служба, отправляющая сообщения, начинает ставить в очередь несколько тысяч сообщений, чтение прекращается, и приложение чтения читает только 2-4 сообщения в секунду. Когда в очередь нет записи, приложение чтения снова может читать до 20 сообщений в секунду.

Код в приложении для чтения довольно прост, разработан на C #, я использую функцию Read (TimeSpan timeout) в System.Messaging.

Q: Почему чтение замедляется, когда отправляется много сообщений в очередь?

Второй вопрос - ограничения TPS

Дополнительный вопрос касается самого чтения. Кажется, нет никакой разницы в том, сколько сообщений я могу прочитать в секунду, если я использую 1 или 5 потоков для чтения из очереди. Я также пробовал реализовать «решение с циклическим перебором», когда почтовая служба отправляет сообщения в случайный набор из 4 очередей, а приложение чтения имело один поток, прослушивающий каждую из этих очередей, но все равно остается только 20 TPS, даже если я чтение из 1 очереди с 1 потоком, 1 очереди с 4 потоками или 4 очередей (с одним потоком на очередь).

Я знаю, что обработка в потоке занимает около 50 мс, поэтому 20 TPS вполне корректно, если одновременно обрабатывается только одно сообщение, но ключ к многопоточности должен заключаться в том, что сообщения обрабатываются параллельно, а не последовательно.

На сервере около 110 различных очередей.

В: Почему я не могу получить более 20 сообщений из очереди одновременно даже при многопоточности и использовании нескольких очередей?

Это это код, выполняющийся сегодня:

// There are 4 BackgroundWorkers running this function
void bw_DoWork(object sender, DoWorkEventArgs e) 
{
    using(var mq = new MessageQueue(".\\content"))
    {
        mq.Formatter = new BinaryMessageFormatter();

        // ShouldIRun is a bool set to false by OnStop()
        while(ShouldIRun)
        {
            try
            {
                using(var msg = mq.Receive(new TimeSpan(0,0,2))
                {
                    ProcessMessageBody(msg.Body); // This takes 50 ms to complete
                }
            }
            catch(MessageQueueException mqe)
            {
               // This occurs every time TimeSpan in Receive() is reached
               if(mqe.MessageQueueErrorCode == MessageQueueErrorCode.IOTimeout) 
                   continue;
            }
        }
    }

Но даже если есть 4 потока, кажется, что все ждут, пока функция снова войдет в точку «Получить». Я также пробовал использовать 4 разные очереди (content1, content2, content3 и content4), но все равно получаю 1 сообщение, обрабатываемое каждые 50 мс.

Имеет ли это какое-либо отношение к TimeSpan в Receive (), и / или можно ли это пропустить?

Другой вопрос, решит ли что-нибудь использование частных очередей, а не публичных?

8
задан Bill the Lizard 28 June 2011 в 16:48
поделиться