Поставленная блокировка недействительна. Либо срок блокировки истек, либо сообщение уже удалено из очереди.

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

public static async Task processCalculations(BrokeredMessage message)
    {
        try
        {
            if (message != null)
            {
                if (connection == null || !connection.IsConnected)
                {
                    connection = await ConnectionMultiplexer.ConnectAsync("connection,SyncTimeout=10000,ConnectTimeout=10000");
                    //connection = ConnectionMultiplexer.Connect("connection,SyncTimeout=10000,ConnectTimeout=10000");
                }

                cache = connection.GetDatabase();

                string sandpKey = message.Properties["sandp"].ToString();
                string dateKey = message.Properties["date"].ToString();
                string symbolclassKey = message.Properties["symbolclass"].ToString();
                string stockdataKey = message.Properties["stockdata"].ToString();
                string stockcomparedataKey = message.Properties["stockcomparedata"].ToString();

                var sandpTask = cache.GetAsync<List<StockData>>(sandpKey);
                var dateTask = cache.GetAsync<DateTime>(dateKey);
                var symbolinfoTask = cache.GetAsync<SymbolInfo>(symbolclassKey);
                var stockdataTask = cache.GetAsync<List<StockData>>(stockdataKey);
                var stockcomparedataTask = cache.GetAsync<List<StockMarketCompare>>(stockcomparedataKey);

                await Task.WhenAll(sandpTask, dateTask, symbolinfoTask,
                    stockdataTask, stockcomparedataTask);

                List<StockData> sandp = sandpTask.Result;
                DateTime date = dateTask.Result;
                SymbolInfo symbolinfo = symbolinfoTask.Result;
                List<StockData> stockdata = stockdataTask.Result;
                List<StockMarketCompare> stockcomparedata = stockcomparedataTask.Result;

                StockRating rating = performCalculations(symbolinfo, date, sandp, stockdata, stockcomparedata);

                if (rating != null)
                {
                    saveToTable(rating);
                    if (message.LockedUntilUtc.Minute <= 1)
                    {
                        await message.RenewLockAsync();
                    }
                    await message.CompleteAsync(); // getting exception here
                }
                else
                {
                    Console.WriteLine("Message " + message.MessageId + " Completed!");
                    await message.CompleteAsync();
                }
            }
        }
        catch (TimeoutException time)
        {
            Console.WriteLine(time.Message);
        }
        catch (MessageLockLostException locks)
        {
            Console.WriteLine(locks.Message);
        }
        catch (RedisConnectionException redis)
        {
            Console.WriteLine("Start the redis server service!");
        }
        catch (MessagingCommunicationException communication)
        {
            Console.WriteLine(communication.Message);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
            Console.WriteLine(ex.StackTrace);
        }
    }

ОБНОВЛЕНИЕ: я проверяю время до истечения срока действия блокировки и вызываю обновление блокировки, если оно необходимо, но оно обновляет блокировку без ошибок, но я все еще получаю это исключение.

timeLeft = message.LockedUntilUtc - DateTime.UtcNow;
  if (timeLeft.TotalMinutes <= 2)
                    {
                        //Console.WriteLine("Renewed lock! " + ((TimeSpan)(message.LockedUntilUtc - DateTime.UtcNow)).TotalMinutes);
                        message.RenewLock();
                    }

catch (MessageLockLostException locks)
        {
            Console.WriteLine("Delivery Count: " + message.DeliveryCount);
            Console.WriteLine("Enqueued Time: " + message.EnqueuedTimeUtc);
            Console.WriteLine("Expires Time: " + message.ExpiresAtUtc);
            Console.WriteLine("Locked Until Time: " + message.LockedUntilUtc);
            Console.WriteLine("Scheduled Enqueue Time: " + message.ScheduledEnqueueTimeUtc);
            Console.WriteLine("Current Time: " + DateTime.UtcNow);
            Console.WriteLine("Time Left: " + timeLeft);
        }

Все, что я знаю до сих пор, это то, что мой код какое-то время работает нормально, и блокировка обновления вызывается и работает, но я все еще получаю исключение блокировки, и внутри этого исключения я вывожу временной левый, и он продолжает увеличивать разницу во времени по мере выполнения кода что заставляет меня поверить, что время до истечения срока блокировки каким-то образом не меняется?


person DarthVegan    schedule 24.01.2015    source источник
comment
Вы когда-нибудь решали это? Что это было?   -  person Fyodor Soikin    schedule 27.02.2015
comment
@FyodorSoikin Нет, мне в конце концов пришлось сдаться и работать над другим методом, чтобы сделать то же самое. Насколько я могу судить, это ошибка в api, но никто из Microsoft никогда не отвечал на мои сообщения.   -  person DarthVegan    schedule 03.03.2015
comment
Может быть, обработка любого из ваших индивидуальных сообщений может занять больше 60 секунд?   -  person DalSoft    schedule 09.03.2015
comment
@DalSoft Я бы возобновил блокировку после завершения интенсивного расчета и прямо перед обработкой сообщения   -  person DarthVegan    schedule 16.03.2015
comment
@ user3610374 вы пытались установить для параметра LockDuration значение 5 минут (что является максимальным значением), значение по умолчанию - 60 секунд, и это исключение будет выдано, если пройдет 60 секунд до обновления блокировки.   -  person DalSoft    schedule 17.03.2015
comment
Да, установка максимального значения была одной из первых вещей, которые я сделал   -  person DarthVegan    schedule 17.03.2015


Ответы (5)


Я часами пытался понять, почему я получил MessageLockLostException. Причина для меня была связана с автозаполнением По умолчанию истина.

Если вы собираетесь вызвать messsage.Complete() (или CompleteAsync()), вам следует создать экземпляр объекта OnMessageOptions, установить для AutoComplete значение false и передать его в вызов OnMessage.

var options = new OnMessageOptions();
options.AutoComplete = false;

client.OnMessage(processCalculations, options);
person Jeffrey LeCours    schedule 01.07.2016
comment
Спасибо, Джеффри, это помогло; Вы можете сказать почему? - person Minhaz; 06.08.2018
comment
@mebjas не следует заполнять сообщение несколько раз. Либо позвольте AutoComplete выполнить работу, либо позаботится об этом самостоятельно (Complete () / CompleteAsync ()), но избегайте того и другого. - person Jeffrey LeCours; 28.12.2018
comment
Будет ли установка autoComplete: false в файле host.json не работать? - person radders; 27.01.2021

У меня была аналогичная проблема. Сообщения обрабатывались успешно, но когда они были завершены, служебная шина больше не имела действующей блокировки. Оказывается, мой TopicClient.PrefetchCount был слишком большим.

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

person solipsicle    schedule 16.06.2017
comment
Каким должно быть количество предварительной выборки? - person Rob McCabe; 12.12.2018
comment
Это то, что сделало это для меня! Настройку счетчика предварительной выборки следует изменить, если вы используете триггеры служебной шины для длительно выполняемых заданий. - person Marcus W; 05.03.2019
comment
@MarcusW, эй, я столкнулся с той же проблемой, что вы установили для счетчика предварительной выборки? Кроме того, есть способ очистить очередь служебной шины, я использую sdk лазурных веб-заданий и не имею прямого доступа к клиенту очереди. - person inquisitive; 01.10.2019
comment
@inquisitive На самом деле я не помню, но попробуйте начать с одного, а затем увеличивать в зависимости от ваших требований к производительности. Что-то вроде игры методом проб и ошибок. Для мониторинга и управления шиной я могу порекомендовать этот инструмент: github.com/paolosalvatori/ServiceBusExplorer/releases - person Marcus W; 02.10.2019

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

        OnMessageOptions options = new OnMessageOptions();

        options.AutoRenewTimeout = TimeSpan.FromMinutes(1);

        try
        {
            client = Subscription.CreateClient();

            client.OnMessageAsync(MessageReceivedComplete, options);
        }
        catch (Exception ex)
        {
            throw new Exception (ex);
        }
person Botha Van Der Vyver    schedule 17.08.2015
comment
Какую версию ServiceBus вы используете? У меня версия v2.2.0.0, и в классе OnMessageOptions нет вызова свойства AutoRenewTimeout. - person Rogala; 25.09.2015
comment
Привет, Рогала. Я использовал версию 2.7.0.0. - person Botha Van Der Vyver; 07.10.2015

В моем случае я просто работал над V2 на моем локальном компьютере, в то время как V1 уже был развернут и работал.

Поскольку V1 был развернут в Azure (ближе к той же очереди) и скомпилирован в режиме выпуска (по сравнению с моей локальной версией в режиме отладки), развернутая версия всегда выигрывала параллелизм для ресурса очереди.

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

person Luis Gouveia    schedule 11.05.2021

На решение аналогичной проблемы у меня ушло 2 дня - такое же исключение.
У этого исключения может быть несколько причин, я опишу пару параметров конфигурации, которые могут помочь вам, незнакомец ...

Конфигурация очереди ServiceBus или тематической подписки:

  • Длительность блокировки сообщений в подписке на очередь / тему слишком мала, установите значение прибл. время обработки сообщения

Конфигурация параметров ServiceBusClient:

  • tryTimeout слишком короткий, установите его ~ 10 с для диагностики.

Конфигурация параметров ServiceBusProcessor:

  • AutoCompleteMessages по умолчанию имеет значение true, установите значение false.
  • PrefetchCount слишком велик, для диагностики установите его равным 0.
  • ReceiveMode установите для него значение ServiceBusReceiveMode.PeekLock.
  • MaxConcurrentCalls для диагностики установите значение 1.

После нахождения правильных значений (оптимизированных для данной системы) я больше не наблюдал никаких проблем.

person Tomas    schedule 05.06.2021