C # - Регулирование MessageQueue - PullRequest
2 голосов
/ 20 октября 2010

У меня есть код, который отправляет сообщение в MessageQueue.

_queue.Send(new Message(myData));

Эта очередь находится на локальном компьютере, и потоки, Receive() из которых находятся в том же процессе.

Что произойдет, если сообщения вставляются быстрее, чем извлекаются?Будет ли Send() блокироваться?Могу ли я узнать, заполнен ли MessageQueue, прежде чем отправлять в него больше событий?(Я бы предпочел на этом этапе просто зарегистрировать myData и не отправлять событие).

Спасибо, Села.

Ответы [ 2 ]

4 голосов
/ 20 октября 2010

Краткий ответ: Делай простую вещь и не ограничивайся отправкой.

Длинный ответ: Очередь сообщений действительно заполнится только тогда, когда на диске, для которого она сохранена, не хватает места - в то же время, когда в журнале будет недостаточно места. Очередь сообщений очень хороша для хранения данных, которые вы не готовы обработать. Не дросселировать при отправке. Если вас беспокоит управление системой и дисковое пространство, то вы можете предпочесть использовать превосходные средства мониторинга системы Windows и предупреждения о пороге использования дискового пространства. Вам не нужно изобретать это для вашего приложения.

То есть, если вы не запускаете очередь в режиме «только память», в этом нет необходимости. Если вы не можете обработать сообщения достаточно быстро, у вас определенно будет достаточно времени, чтобы администратор очередей сохранил сообщения на диск. Рассматривать запуск очереди в режиме «только память» следует только в том случае, если вы собираетесь масштабировать до множества пользовательских процессов на многих серверах, а дисковый ввод-вывод в администраторе очередей становится узким местом. Один процесс на той же машине очень далек от этого сценария. Пусть администратор очередей сделает то, что умеет лучше всего. Не оптимизируйте преждевременно.

Если вы реализуете определенное качество обслуживания, например, X сообщений в секунду, и платите своим клиентам больше за обработку более высокого качества обслуживания, чем подавляете на принимающей стороне. Я сделал это успешно, используя семафор, инициализированный с лимитом ресурсов, равным количеству сообщений, потребляемых в секунду. Каждый потребительский поток делал снимок времени начала сообщения, обрабатывал 1 сообщение и затем ждал конца секунды, прежде чем отказаться от семафора. Таким образом, пул потоков может увеличиваться для обеспечения качества обслуживания, если обработка сообщений занимает более 1 секунды, но не превышает качество обслуживания.

Удачи!

1 голос
/ 22 июня 2012

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

Чтобы подготовиться к такой ситуации, необходимо следить за успешностью метода Send(). Если вы отправляете сообщение в полную очередь, оно теряется, и, поскольку Send() возвращает void, немедленного успеха или неудачи не будет. Но есть способ обнаружить это. Вы должны запросить подтверждение при работе с MSMQ. Для их получения необходимо использовать административную очередь. Таким образом, вы можете получать уведомления о различных событиях, включая заполнение очереди.

Message msg = new Message
{
    Formatter = new BinaryMessageFormatter(),
    Body = data,
    AdministrationQueue = this.adminQueue,
    AcknowledgeType = AcknowledgeTypes.FullReachQueue
};

this.queue.Send(msg);

Message admMsg = this.adminQueue.Receive();
if (admMsg != null && admMsg.Acknowledgment == Acknowledgment.QueueExceedMaximumSize)
{
    // queue is full
}
...