Краткое введение
У меня есть система на основе 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 (), и / или можно ли это пропустить?
Другой вопрос, решит ли что-нибудь использование частных очередей, а не публичных?