簡體   English   中英

Azure Servicebus主題continueos接收器消息停止

[英]Azure Servicebus Topic continuos Receiver message stops

我構建了一個Azure服務總線消息提供程序,以在具有核心2.0的Linux CENTOS 7中運行。 我正在使用“ Microsoft.Azure.ServiceBus 3.1.0”包。 但是,當我收到五十萬(500,000)或更多的消息時,即使有許多要讀取的活動消息,“ RegisterMessageHandler”也會停止,不再接收了。 我有五個線程,五分鍾內有“ MaxConcurrentCall”(一百個),“ Prefechcount”(一百)和“ MaxAutoRenewDuration”(五個)。

此方法使用“ RegisterMessageHandler”來連續讀取訂閱。

public async Task RecebeMensagemAsync(CancellationToken cancellationToken, Action<string> tratarObjetoImportado, int prefetchCount)
    {
        try
        {
            var receiver = new Microsoft.Azure.ServiceBus.SubscriptionClient(_serviceBusConnString, _topic, _subscription, this._receiveMode, new RetryExponential(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(10), _retryPolicyMaximumRetryCount));
            receiver.PrefetchCount = prefetchCount;
            receiver.OperationTimeout = TimeSpan.FromMinutes(_timoutOperacao);
            var cicloRecebimentoCompleto = new TaskCompletionSource<bool>();

            // fecha receiver e factory quando o CancellationToken é acionado
            cancellationToken.Register(
                async () =>
                {
                    await receiver.CloseAsync();
                    cicloRecebimentoCompleto.SetResult(true);
                });

            // registra o RegisterMessageHandler para tratar mensagem lida assincronamente
            receiver.RegisterMessageHandler(
                async (message, cancellationTokenResponse) =>
                {
                    if (message.Body == null || message.Body.Length == 0)
                    {
                        GerenciadorLog.LogInfo($"Mensagem não possui conteudo, mensageId: {message.MessageId}", LogType.Warning);
                        await receiver.CompleteAsync(message.SystemProperties.LockToken);
                    }
                    else
                    {
                        try
                        {
                            tratarObjetoImportado(Encoding.UTF8.GetString(message.Body));

                            if (_receiveMode == ReceiveMode.PeekLock)
                                await receiver.CompleteAsync(message.SystemProperties.LockToken);
                        }
                        catch (MessageSizeExceededException ex) {
                            GerenciadorLog.LogError($"Tamanho da mensagem:{message.MessageId}", ex);
                            try
                            {
                                if (_receiveMode == ReceiveMode.PeekLock)
                                    await receiver.DeadLetterAsync(message.SystemProperties.LockToken);
                            }
                            catch (Exception dlex)
                            {
                                GerenciadorLog.LogError($"Erro ao enviar mensagem para 'DeadLetter', mensageId: {message.MessageId}", dlex);
                                throw new Exception("Erro não identificado", dlex);
                            }
                        }
                        catch (MessageLockLostException ex)
                        {
                            GerenciadorLog.LogError($"Expirou tempo de leitura da mensagem, será enviada para DeadLetter:{message.MessageId}", ex);
                            try
                            {
                                await receiver.AbandonAsync(message.SystemProperties.LockToken);
                            }
                            catch (Exception ex2)
                            {
                                GerenciadorLog.LogError($"Erro ao abandonar mensagem, mensageId:{message.MessageId}", ex2);
                                await Task.CompletedTask;
                            }
                        }
                        catch (MessagingEntityNotFoundException ex)
                        {
                            GerenciadorLog.LogError($"Mensagem não encontrada, mensageId:{message.MessageId}", ex);
                            try
                            {
                                await receiver.AbandonAsync(message.SystemProperties.LockToken);
                            }
                            catch (Exception ex2)
                            {
                                GerenciadorLog.LogError($"Erro ao abandonar mensagem, mensageId:{message.MessageId}", ex2);
                                await Task.CompletedTask;
                            }
                        }
                        catch (Exception ex)
                        {
                            if (ex != null && !string.IsNullOrEmpty(ex.Message))
                                GerenciadorLog.LogError($"Erro na importação, mensageId:{message.MessageId}", ex);

                            try
                            {
                                if (_receiveMode == ReceiveMode.PeekLock)
                                    await receiver.DeadLetterAsync(message.SystemProperties.LockToken);
                            }
                            catch (Exception dlex)
                            {
                                GerenciadorLog.LogError($"Erro ao enviar mensagem para 'DeadLetter', mensageId: {message.MessageId}", dlex);
                                await Task.CompletedTask;
                            }
                        }
                    }
                },
                new MessageHandlerOptions((e) => LogMessageHandlerException(e, receiver)) { AutoComplete = false, MaxConcurrentCalls = _maxConcurrentCalls, MaxAutoRenewDuration = TimeSpan.FromSeconds(_lockDuration) });
            await cicloRecebimentoCompleto.Task;
        }
        catch (Exception ex)
        {
            GerenciadorLog.LogError("Erro ao configurar 'listener' para leitura das mensagens.");
            GerenciadorLog.LogError(ex.Message, ex);
            throw ex;
        }
    }

並且此方法一直等待任務。 可以有多個線程調用此方法

        public async Task Run(int segundosIntnervaloSondaConsultaTopico, int prefetchCount, Action<string> tratarObjetoImportado)
    {
        IList<CancellationTokenSource> cancellationTokensSource = new List<CancellationTokenSource>();
        IList<Task> instanciasDasSondas = new List<Task>();
        CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
        GerenciadorLog.LogInfo($"start blablalbala --");

        var recebeMensagemAsync = RecebeMensagemAsync(cancellationTokenSource.Token, tratarObjetoImportado, prefetchCount);

        await Task.WhenAll(Task.Run(() => Console.ReadKey()),
            Task.Delay(TimeSpan.FromSeconds(segundosIntnervaloSondaConsultaTopico)).ContinueWith((t) => cancellationTokenSource),
            Task.WhenAll(new Task[] { recebeMensagemAsync }));
    }

有人知道繼續運行或續訂注冊客戶端的正確方法,還是其他方法?

在更新到“ Microsoft.Azure.ServiceBus 3.1.1”程序包后,此問題已修復:

https://www.nuget.org/packages/Microsoft.Azure.ServiceBus/

韓國社交協會。

暫無
暫無

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

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