简体   繁体   中英

Azure Servicebus Topic continuos Receiver message stops

I builded a Azure Service Bus Message provider to run in linux CENTOS 7 with core 2.0. I'm using the packge "Microsoft.Azure.ServiceBus 3.1.0". But when I receive five hundred thousand(500 000) or more messages, the "RegisterMessageHandler" stop even with many active messages to read, does't receive anymore. I have five threads, "MaxConcurrentCall" with one hundred, Prefechcount 100 and "MaxAutoRenewDuration" in five minutes.

This method use "RegisterMessageHandler" to keep reading subscription continuously.

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

And this method keep await the task. Can have more than one thread calling this method

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

Somebody knows the correct way to keep running or renew the client of register, or another approach?

It was fixed after update to "Microsoft.Azure.ServiceBus 3.1.1" package:

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

tks.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM