Каков правильный способ отказаться от сообщения Azure SB, чтобы он стал видимым снова в будущем таким образом, каким я могу управлять?
Итак, сценарий заключается в том, что я использую очередь SB, чтобы отключить исходящие обратные вызовы другим службам. Одна из стандартных проблем с обращением к другим службам заключается в том, что они могут быть недоступны для неконтролируемого количества времени. Предполагая, что я обнаруживаю, что цель отключена/не отвечает, каков наилучший шаблон для отказа от этого сообщения, чтобы он не появлялся сразу в очереди?
Вот некоторые подходы, о которых я либо знаю, пробовали или рассматриваю:
-
Очевидно, что если я просто использую BrokeredMessage::Abandon()
, сообщение будет разблокировано и помещено обратно в очередь. Это явно нежелательно для этого сценария и того, чего я пытаюсь избежать.
-
Если я просто проигнорирую тот факт, что я столкнулся с ошибкой и никогда не вызываю Abandon, это не позволит ему немедленно появиться, но я действительно не обладаю тонким контролем над тем, как долго это будет отображаться снова и Я хотел бы реализовать разлагающуюся стратегию повтора.
-
Я подумал, может быть, я мог бы назвать BrokeredMessage::Abandon(IDictionary<string, object>)
и каким-то образом обновить свойство ScheduledEnqueueTimeUTC
, но я пробовал это, и, похоже, не существует способа повлиять на это свойство за пределы начальной отправки сообщения, Имеет смысл, но мысль стоит попробовать.
-
Я рассмотрел только использование BrokeredMessage::Complete()
в этой ситуации и фактически просто присвоил новую копию сообщения с помощью набора свойств ScheduledEqueueTimeUTC
.
Конечная пуля почти кажется слишком тяжелой, но я прихожу к выводу, что это, вероятно, правильный ответ, учитывая присущую природе очередей. Я просто подумал, что может быть более приятный способ сделать это в очередях Azure SB, которые мне не хватает.
Ответы
Ответ 1
Если вы хотите некоторое время отложить сообщение, и у вас есть место для записи SequenceNumber (который может находиться в состоянии сеанса в сеансовой очереди), вы можете его отменить(). Отложенные сообщения могут быть получены с помощью специальной перегрузки Receive, предоставляющей SequenceNumber; что также единственный способ получить их снова, кроме них, истекающих, так осторожно. Эта функция была создана для рабочих процессов и состояний машин, чтобы они могли справиться с прибытием сообщения вне заказа.
Ответ 2
В bullet # 2 выше: Не можете ли вы установить время TTL в сообщении при вызове Receive(TimeSpan)
вместо стандартного Receive()
? Затем вы можете просто отказаться от сообщения (без вызова Abandon()
), и сообщение должно появиться в очереди, когда истечет срок действия TTL. Хотя это не дает вам тонкого контроля, чтобы сказать "Повторить через x секунд", это дает вам предсказуемость, когда сообщение снова появляется.
Примечание. С очередями на основе хранилища вы можете обновить тайм-аут невидимости, чтобы дать вам управление тонкой зернистостью для повторного появления сообщения.
Ответ 3
Чувствует себя немного взломанным, но решение, которое я придумал, -
try
{
...
}
catch (Exception ex)
{
await Task.Delay(30000);
throw;
}
Таким образом, он будет ждать 30 секунд, прежде чем позволить ему отказаться. Это будет в конечном итоге мертвая буква после настроенного количества раз.
Я использую Azure Webjob для получения.
Хотя я использую Task.Delay
вместо Thread.Sleep
, он, похоже, не освобождает поток для обработки другого элемента из очереди во время ожидания (по умолчанию, Webjobs обрабатывает 16 параллельно).
Ответ 4
Если бы я был вами, я бы посоветовал один из многих шаблонов интеграции предприятия, которые находятся в Интернете для решения. В принципе, вы хотите иметь повторную попытку, которая, если она прерывается, отправляет сообщение в очередь с мертвой буквой. Эти сообщения затем могут быть запрошены позднее. Это может быть ручным или автоматическим в зависимости от требований.
Обратите внимание, что пока страница, которую я отправил вам, связана с верблюдом, и поэтому java все, что описано на этой странице, применимо .NET и azure. Вот еще один .NET, если ваш заинтересованный http://www.eaipatterns.com/
Ответ 5
Я предпочел бы последний подход, потому что это, кажется, самое простое решение, использующее встроенные функции служебной шины Azure.
Поток таков:
var newMessage = new BrokeredMessage();
// Copy message body and properties from original message...
var scheduleTimeUtc = DateTimeOffset.UtcNow.Add(...);
await queueClient.ScheduleMessageAsync(newMessage, scheduleTimeUtc);
await originalMessage.CompleteAsync()