programing

제공된 잠금이 잘못되었습니다.잠금이 만료되었거나 메시지가 대기열에서 이미 제거되었습니다.

padding 2023. 5. 23. 21:36
반응형

제공된 잠금이 잘못되었습니다.잠금이 만료되었거나 메시지가 대기열에서 이미 제거되었습니다.

Microsoft 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);
        }

제가 지금까지 알고 있는 것은 코드가 잠시 동안 잘 실행되고 갱신 잠금이 호출되어 작동하지만 여전히 잠금 예외가 발생하고 있으며 그 예외 안에서 남은 시간을 출력하고 코드가 실행됨에 따라 시간 차이가 계속 증가하여 잠금 만료까지의 시간이 어떻게든 변경되지 않고 있다고 믿게 합니다.

저는 제가 왜 병원에 입원했는지 이해하기 위해 몇 시간을 보냈습니다.MessageLockLostException자동 완성이 true로 기본 설정되었기 때문입니다.

전화하실 거라면messsage.Complete()(또는)CompleteAsync()) 은 그런다인해합니다야화스턴스를 해야 합니다OnMessageOptions 체, 트AutoComplete거짓으로, 그리고 그것을 당신의 것으로 전달합니다.OnMessage콜.콜.

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

client.OnMessage(processCalculations, options);

유사한 문제를 해결하는 데 이틀이 걸렸습니다. 동일한 예외입니다.
이 예외에는 여러 가지 이유가 있을 수 있습니다. 모르는 사람에게 도움이 될 수 있는 몇 가지 구성 옵션을 설명하겠습니다.

서비스 버스 대기열 또는 주제-구독 구성:

  • 대기열/주제 구독의 메시지 잠금 기간이 너무 낮습니다. 약 메시지 처리 시간으로 설정하십시오.

ServiceBusClient 옵션 구성:

  • tryTimeout이 너무 짧습니다. 진단을 위해 ~10초로 설정합니다.

ServiceBusProcessor 옵션 구성:

  • AutoCompleteMessages는 기본적으로 true로 설정되며 false로 설정됩니다.
  • PrefetchCount가 너무 높습니다. 진단을 위해 0으로 설정합니다.
  • 수신 모드는 서비스 버스 수신 모드로 설정합니다.PeekLock
  • MaxConcurrentCalls for Diagnostics는 1로 설정했습니다.

올바른 값을 찾은 후(지정된 시스템에 최적화됨)저는 더 이상 어떤 문제도 관찰하지 않았습니다.

저도 비슷한 문제를 겪고 있었습니다.메시지가 성공적으로 처리되고 있지만 메시지가 완료되면 서비스 버스에 더 이상 유효한 잠금이 없습니다.제 토픽 클라이언트입니다.PrefetchCount가 너무 높습니다.

사전 추출된 모든 메시지를 가져오는 즉시 잠금이 시작되는 것으로 나타납니다.누적 메시지 처리 시간이 잠금 제한 시간을 초과하면 다른 모든 사전 추출된 메시지가 완료되지 않습니다.그것은 서비스 버스로 돌아갈 것입니다.

저의 경우에는 V1을 이미 구축한 상태에서 로컬 시스템에서 V2 작업을 수행하고 있었습니다.

V1이 Azure(동일한 큐에 가까운)에 배포되고 릴리스 모드(디버깅 모드의 로컬 버전과 비교)에서 컴파일되었기 때문에 배포된 버전은 항상 대기열 리소스에 대한 동시성을 "획득"했습니다.

메시지가 더 이상 대기열에 없는 이유입니다. 배포된 버전의 코드에서 사용되었습니다.나는 그것이 약간 멍청하다는 것을 압니다.

잠금을 수동으로 갱신하는 대신 클라이언트 헤드라인 등록을 만들 때 다음과 같은 클라이언트의 OnMessage 옵션()을 사용하여 자동으로 갱신해 보십시오.

        OnMessageOptions options = new OnMessageOptions();

        options.AutoRenewTimeout = TimeSpan.FromMinutes(1);

        try
        {
            client = Subscription.CreateClient();

            client.OnMessageAsync(MessageReceivedComplete, options);
        }
        catch (Exception ex)
        {
            throw new Exception (ex);
        }

언급URL : https://stackoverflow.com/questions/28127001/the-lock-supplied-is-invalid-either-the-lock-expired-or-the-message-has-alread

반응형