我构建了一个Azure服务总线消息提供程序,以在具有核心2.0的Linux CENTOS 7中运行。我正在使用“ Microsoft.Azure.ServiceBus 3.1.0”包。但是当我收到 五十万(500 000)个或更多消息时,即使有许多要读取的活动消息,“ RegisterMessageHandler”也会停止,不再接收。我有五个线程,五分钟内有“ MaxConcurrentCall”和一百个线程,Prefechcount 100和“ 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 }));
}
有人知道保持运行或更新注册客户端的正确方法,还是另一种方法?
答案 0 :(得分:0)
在更新为“ Microsoft.Azure.ServiceBus 3.1.1”程序包后已修复:
https://www.nuget.org/packages/Microsoft.Azure.ServiceBus/
tks。