Rebus Azure ServiceBus - Отсутствует идентификатор сообщения для сообщения, отправленного из внешней службы

Я создаю Proof of Concept с помощью Rebus по отношению к служебной шине Azure, однако у меня возникла небольшая проблема при синтаксическом анализе сообщения, помещенного в очередь из внешнего источника.

Я получаю сообщение об ошибке:

Получено сообщение с пустым или отсутствующим заголовком rbs2-msg-id!

Я просмотрел GitHub и заметил этот листинг о том, что у кого-то была аналогичная проблема для RabbitMQ, и было рекомендовано использовать декоратор:

https://github.com/rebus-org/Rebus/issues/508

Однако я не уверен, как это сделать только для идентификатора сообщения.

Один из вариантов, который я выбрал, - это изменить код Rebus.AzureTransport, чтобы сделать это:

var messageId = headers.GetValueOrNull(Headers.MessageId);

if (string.IsNullOrEmpty(messageId))
{
    messageId = Guid.NewGuid().ToString();
    headers[Headers.MessageId] = messageId;
}

Но предпочел бы альтернативу!

Еще я заметил, что BrokeredMessage помещается в ASB следующим образом:

var message = new BrokeredMessage("<xml>This is a test message: " + DateTime.Now+ "</xml>");

Он некорректно сериализуется при получении Ребусом. Я получаю следующую ошибку:

Необработанное исключение 1 при обработке сообщения с идентификатором db13880d-124c-4ed5-993e-96faeca0f140: System.Collections.Generic.KeyNotFoundException: не удалось найти ключ 'rbs2-content-type'

При отмене сериализатора нижеследующее сообщение выглядит как:

@ strin3 http://schemas.microsoft.com/2003/10/Serialization/? 6 Это тестовое сообщение: 06/12/2016 07:44:21

поэтому я не уверен, что делаю не так.

Заранее спасибо.


person jazzyuk    schedule 06.12.2016    source источник


Ответы (1)


Что ж ... как говорится в сообщениях об ошибках, входящее сообщение не содержит достаточной информации, чтобы Ребус мог его обработать.

Более того, транспортная шина служебной шины Azure Rebus требует, чтобы содержимое сообщения отправлялось как Stream, чтобы избежать затрат на включение содержащихся байтов в структуру XML (что драйвер служебной шины Azure делает по умолчанию).

На вашем месте я бы, вероятно, не использовал Rebus для получения сообщений из очереди, не содержащей сообщений, отправленных Rebus. Или я мог бы это сделать - но только если бы входящие сообщения было очень легко адаптировать, чтобы они соответствовали формату Rebus.

Однако это может быть немного громоздко, потому что, как вы правильно заметили, для этого требуются определенные заголовки, которые действуют как подсказки для Rebus о том, как отслеживать его между попытками обработки, как десериализовать его, где чтобы ответить, если вызывается bus.Reply и т. д. Так что я все равно могу закончить тем, что не буду этого делать :)

Предлагаю вам сделать что-то вроде этого:

while(true)
{
    var message = GetNextMessageOrNullFromQueue();

    if (message == null) continue;

    UnwrapMessageAndSendWithRebusToRebusQueue(message);
}

таким образом кодируйте собственный цикл приема для получения сообщений служебной шины Azure в настраиваемом формате, делегируя фактическую обработку их (возможно, также десериализацию из текста XML в объекты?) конечной точке Rebus.

Как правило, это предпочтительный способ интеграции с внешними объектами, поскольку он сохраняет логику перехода между внешним и внутренним частями вашего приложения по периметру, вместо того, чтобы проникать в ваше приложение.

person mookid8000    schedule 06.12.2016
comment
Привет, спасибо за ответ. Я рассмотрю возможность использования цикла приема. Одна вещь, в которой я не был уверен: почему сообщение будет неправильно выбрано из очереди, когда я переопределил сериализатор (я использовал сериализатор Utf8Fallback в вашем примере ReceiveNonRebusMessageWithRabbitMq). Я бы подумал, что это будет правильно разобрать? - person jazzyuk; 06.12.2016
comment
ты нашел ответ? какая рекомендация по состоянию на 2021 год? - person Maulik Modi; 17.07.2021
comment
Та же рекомендация: получайте сообщения служебной шины Azure в настраиваемом формате в выделенном цикле приема, используйте односторонний клиент Rebus, чтобы пересылать его как правильное сообщение Rebus в очередь Rebus. - person mookid8000; 17.07.2021