簡體   English   中英

Azure服務總線消息鎖是否未續訂?

[英]Azure Service Bus message lock not being renewed?

我建立了一項服務來支持Azure Service Bus中的多個隊列訂閱,但是出現了一些奇怪的現象。

我的訂閱單例類具有如下所示的方法:

    public void Subscribe<TMessage>(Func<TMessage, Task> execution, int maxDop = 1, int ttl = 60) where TMessage : IServiceBusMessage
    {
        try
        {
            var messageLifespan = TimeSpan.FromSeconds(ttl);
            var messageType = typeof(TMessage);
            if (!_activeSubscriptionClients.TryGetValue(messageType, out var subscriptionClient))
            {
                subscriptionClient = _subscriptionClientFactory.Create(typeof(TMessage)).GetAwaiter().GetResult();
                if (subscriptionClient.OperationTimeout < messageLifespan) subscriptionClient.OperationTimeout = messageLifespan;
                if (subscriptionClient.ServiceBusConnection.OperationTimeout < messageLifespan)
                    subscriptionClient.ServiceBusConnection.OperationTimeout = messageLifespan;
                _activeSubscriptionClients.AddOrUpdate(messageType, subscriptionClient, (key, value) => value);
            }

            var messageHandlerOptions = new MessageHandlerOptions(OnException)
            {
                MaxConcurrentCalls = maxDop,
                AutoComplete = false,
                MaxAutoRenewDuration = messageLifespan,
            };


            subscriptionClient.RegisterMessageHandler(
                async (azureMessage, cancellationToken) =>
                {
                    try
                    {
                        var textPayload = _encoding.GetString(azureMessage.Body);
                        var message = JsonConvert.DeserializeObject<TMessage>(textPayload);
                        if (message == null)
                            throw new FormatException($"Cannot deserialize the message payload to type '{typeof(TMessage).FullName}'.");
                        await execution.Invoke(message);
                        await subscriptionClient.CompleteAsync(azureMessage.SystemProperties.LockToken);
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError(ex, "ProcessMessagesAsync(Message, CancellationToken)");
                        await subscriptionClient.AbandonAsync(azureMessage.SystemProperties.LockToken);
                    }
                }
                , messageHandlerOptions);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Subscribe(Action<TMessage>)");
            throw;
        }
    }

這個想法是,您為特定類型的消息訂閱Azure Service Bus,並且該消息直接對應於隊列。 在您的訂閱中,您傳遞了有關如何處理消息的委托。

這似乎奏效了。。。

無論我在長時間運行的任何給定消息上為MaxAutoRenewDurationOperationTimeout設置ttl MaxAutoRenewDuration ,一分鍾后都會將該消息從隊列中解鎖,然后另一個訂戶將其拾起並開始處理它。

我的理解是,這正是MaxAutoRenewDuration應該防止的……但是似乎並沒有阻止任何東西。

誰能告訴我我需要做些什么來確保消費者擁有該信息直至完成?

我可以想到一些選項,您可能需要考慮一下。

  1. 而不是在SubscriptionClient中使用默認的ReceiveMode = PeekLock ,而是將其設置為ReceiveAndDelete,這樣,一旦使用了一條消息,它將被從隊列中刪除,並且不會被任何其他客戶端使用,這意味着您必須處理異常優雅地進行重試;

  2. 看看OperationTimeout ,根據doco的Duration after which individual operations will timeout

事實證明,使用者正在運行的遠程進程正在靜默失敗,並且未返回失敗狀態代碼(或其他任何信息); 自動刷新機制掛起等待結果,因此該消息最終超時。

我不清楚如何避免這種情況,但是一旦我在遠程進程上解決了該問題,該問題就不再可重現了。

故事的寓意:如果一切正常,但仍在超時,似乎自動刷新機制與您正在等待的異步操作共享了一些資源。 這可能是尋找失敗的另一個地方。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM