Руководство OnMessageOptions.AutoRenewTimeout

Может ли кто-нибудь предложить дополнительные рекомендации по использованию Azure Service Bus OnMessageOptions.AutoRenewTimeout http://msdn.microsoft.com/en-us/library/microsoft.servicebus.messaging.onmessageoptions.autorenewtimeout.aspx

поскольку я не нашел много документации по этому параметру и хотел бы знать, является ли это правильным способом обновления блокировки сообщений

Мой прецедент:

1) Очередь обработки сообщений имеет продолжительность блокировки 5 минут (максимально допустимое)

2) Обработчик сообщений с помощью насоса сообщений OnMessageAsync для чтения из очереди (с помощью ReceiveMode.PeekLock) Длительная обработка может занять до 10 минут для обработки сообщения перед вызовом вручную msg.CompleteAsync

3) Я хочу, чтобы процессор сообщений автоматически возобновил его блокировку до момента, когда он ожидал завершения обработки (~ 10 минут). Если после этого периода он не был завершен, блокировка должна быть автоматически отпущена.

Спасибо

- ОБНОВЛЕНИЕ

Я никогда не получал больше рекомендаций по AutoRenewTimeout. Я закончил использование специального класса MessageLock, который автоматически обновляет блокировку сообщений на основе таймера.

См. суть - https://gist.github.com/Soopster/dd0fbd754a65fc5edfa9

Ответы

Ответ 1

Чтобы обрабатывать длительную обработку сообщений, вы должны установить AutoRenewTimeout == 10 минут (в вашем случае). Это означает, что блокировка будет обновляться в течение этих 10 минут каждый раз, когда истечет время LockDuration.

Итак, если, например, ваш LockDuration составляет 3 минуты, а AutoRenewTimeout - 10 минут, то каждые 3 минуты блокировка автоматически возобновляется (через 3 мин, 6 мин и 9 мин), а блокировка автоматически отпускается через 12 минут поскольку сообщение было уничтожено.

Ответ 2

У меня такая же проблема с моими работниками. Даже сообщение успешно обрабатывалось из-за длительного времени обработки, служебная шина удаляет блокировку, применяемую к ней, и сообщение становится доступным для получения снова. Другой доступный работник принимает это сообщение и начинает его снова обрабатывать. Пожалуйста, исправьте меня, если я ошибаюсь, но в вашем случае OnMessageAsync будет вызываться много раз с тем же сообщением, и вам будет предоставлено несколько задач, одновременно обрабатывающих его. В конце процесса будет вызвано исключение MessageLockLost, потому что сообщение не имеет блокировки. Я решил это с помощью следующего кода.

_requestQueueClient.OnMessage(
            requestMessage =>
            {
                RenewMessageLock(requestMessage);
                var messageLockTimer = new System.Timers.Timer(TimeSpan.FromSeconds(290));
                messageLockTimer.Elapsed += (source, e) =>
                {
                    RenewMessageLock(requestMessage);
                };
                messageLockTimer.AutoReset = false; // by deffault is true
                messageLockTimer.Start();

                /* ----- handle requestMessage ----- */

                requestMessage.Complete();

                messageLockTimer.Stop();
            }

 private void RenewMessageLock(BrokeredMessage requestMessage)
    {
        try
        {
            requestMessage.RenewLock();
        }
        catch (Exception exception)
        {

        }
    }

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

Ответ 3

По моим личным предпочтениям OnMessageOptions.AutoRenewTimeout является слишком грубым вариантом продления аренды. Если установить его на 10 минут, и по какой-либо причине Сообщение будет .Complete() только через 10 минут и 5 секунд, сообщение снова появится в очереди сообщений, будет использовано следующим резервным рабочим и всем обработка будет выполнена снова. Это расточительно и также не дает работникам выполнять другие необработанные запросы.

Чтобы обойти это:

  1. Измените рабочий процесс, чтобы убедиться, что элемент, который он только что получил из очереди сообщений, еще не был обработан. Посмотрите на результат успеха/неудачи, который хранится где-то. Если процесс уже выполнен, вызовите BrokeredMessage.Complete() и переходите к ожиданию появления следующего элемента.

  2. Периодически вызывайте BrokeredMessage.RenewLock() - ДО истечения срока блокировки, как каждые 10 секунд, - и установите для OnMessageOptions.AutoRenewTimeout значение TimeSpan.Zero. Таким образом, если рабочий, который обрабатывает элемент, аварийно завершает работу, сообщение вернется в MessageQueue раньше и будет получен следующим резервным рабочим.