Выборочное чтение из очереди — настраиваемая служба MSMQ, ESB или что-то еще?

Ищу некоторые идеи/шаблоны для решения проблемы проектирования системы, над которой я скоро начну работать. Нет никаких сомнений в том, что мне нужно будет использовать какой-то обмен сообщениями (вероятно, MSMQ) для связи между определенными областями системы. Я не хочу изобретать велосипед, но в то же время я хочу убедиться, что использую правильный инструмент для работы. Я возился с NServiceBus и читал о нем, и я очень впечатлен тем, что он делает, однако я не уверен, что он предназначен для того, чего я пытаюсь достичь.

Вот (надеюсь) очень простое и концептуальное описание того, что должна делать система:

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

Обработка/обработка каждого сообщения нетривиальна и может занимать значительные системные ресурсы. По этой причине одновременно могут обрабатываться только сообщения X, где X — настраиваемое значение (на основе спецификаций системы и т. д.). Входящие сообщения будут храниться в очереди до тех пор, пока не наступит «их очередь» для обработки.

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

В настоящее время я думаю, что мне просто нужно использовать vanilla MSMQ, создать службу для приема сообщений и записи их в одну или несколько очередей, а затем создать процесс для чтения сообщений из очередей и обработки/обработки их. Однако надежность, аудит, масштабируемость и простота настройки, которые вы получаете с чем-то вроде NServicebus, выглядят очень привлекательно.

Является ли ESB неподходящим инструментом для работы? Есть ли какая-то другая технология или шаблон, на который я должен обратить внимание?

Обновить

Несколько уточнений.

Что касается обработки сообщений «по порядку» — в контексте одного клиента сообщения абсолютно необходимо обрабатывать в том порядке, в котором они получены. Трудно объяснить точные причины, почему, но это твердое требование. Я не упомянул, что одновременно может обрабатываться только одно сообщение для каждого клиента. Таким образом, даже если бы было 10 рабочих потоков и только у одного клиента были сообщения, ожидающие обработки, только одно из этих сообщений было бы обработано за раз — можно было бы не беспокоиться о состоянии гонки.

Я считаю, что это вообще возможно с ванильным MSMQ - вы можете иметь список сообщений в очереди и всегда сначала брать самое старое.

Я также хотел уточнить вариант использования циклического заказа. В этом примере у меня есть два клиента (A и B), которые отправляют сообщения, и только один рабочий поток. Все очереди пусты. Клиент А потерял подключение за ночь, поэтому в 8 утра отправляет в службу 1000 сообщений. Эти сообщения ставятся в очередь, и рабочий поток берет самое старое и начинает его обработку. Когда это первое сообщение обрабатывается, клиент B отправляет сообщение в службу, которое ставится в очередь (как уже отмечалось, возможно, в отдельной очереди). Когда первое сообщение клиента A завершает обработку, логика должна проверить, есть ли у клиента B сообщение (это «очередь» клиента B), и, поскольку он находит его, обработать его следующим.

Если клиент B не отправил сообщение в течение этого времени, рабочий процесс будет продолжать обрабатывать сообщения клиента A по одному, всегда проверяя после обработки, чтобы увидеть, содержат ли другие клиентские очереди ожидающие сообщения, чтобы убедиться, что ни один клиент не голодает.

Где я все еще чувствую, что может быть несоответствие между ESB, и эта проблема заключается в том, что ESB разработан для облегчения связи между службами; то, чего я пытаюсь достичь, - это комбинация обмена сообщениями/общения и избирательной системы очередей.


person Phil Sandler    schedule 23.08.2010    source источник


Ответы (2)


Использование ESB, такого как NServiceBus, кажется хорошим решением вашей проблемы. Но, основываясь на вашем концептуальном описании, есть некоторые вещи, которые следует учитывать. Давайте рассмотрим ваши требования шаг за шагом, используя NServiceBus в качестве возможного решения ESB:

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

Это легко сделать с помощью NServiceBus. Вы можете Bus.Send(Message) от клиента. Если вашему клиенту требуется ответ, вы можете использовать Bus.Return(ErrorCode). Вы упоминаете, что «успех в том, что сообщение было получено». Если вы используете ESB, например NServiceBus, доставка сообщения зависит от платформы обмена сообщениями. Таким образом, если ваш Bus.Send не генерирует исключение, вы можете быть уверены, что сообщение было отправлено правильно. Из-за этого вам, вероятно, не придется отправлять клиенту сообщения об успешном/неудачном выполнении.

Обработка/обработка каждого сообщения нетривиальна и может занимать значительные системные ресурсы. По этой причине одновременно могут обрабатываться только сообщения X, где X — настраиваемое значение (на основе спецификаций системы и т. д.). Входящие сообщения будут храниться в очереди до тех пор, пока не наступит «их очередь» для обработки.

При использовании NServiceBus вы можете настроить количество рабочих потоков, установив параметр «NumberOfWorkerThreads». Если ваш сервер имеет несколько ядер/процессоров, вы можете использовать этот параметр для балансировки рабочей нагрузки.

Для каждого клиента сообщения должны обрабатываться по порядку (FIFO).

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

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

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

По этой причине сообщения должны обрабатываться в циклическом режиме между клиентами — ни один клиент не может переедать и ни один клиент не может голодать.

Это не проблема, потому что вы решили использовать сообщения :)

Таким образом, система должна либо иметь возможность запрашивать очередь для конкретного клиента, либо создавать отдельные очереди для каждого клиента (автоматически, поскольку клиенты не будут известны во время компиляции) и извлекать из них поочередно.

Не могли бы вы расширить это? Я не уверен в вашем дизайне на этом.

person Mikael Koskinen    schedule 23.08.2010
comment
См. ответ Джона - по линии создания отдельных очередей по требованию. Я добавлю больше информации к моему вопросу в ближайшее время. Спасибо за Ваш ответ. - person Phil Sandler; 23.08.2010

person    schedule
comment
Да, я был почти уверен, что поиск в очереди не лучший вариант, особенно когда там десятки тысяч сообщений. Я больше думал о сервисе, создающем их по запросу. Спасибо за Ваш ответ. - person Phil Sandler; 23.08.2010