Solucionar problemas do processador de eventos dos Hubs de Eventos do Azure

Este artigo ajuda-o a resolver problemas com o processador de eventos do Hubs de Eventos do Azure quando utiliza este EventProcessorClient tipo. Usa-o para resolver problemas comuns de propriedade, CPU, memória e recetor. Para soluções para outros problemas comuns que possa encontrar ao utilizar o Hubs de Eventos do Azure, consulte Troubleshoot Hubs de Eventos do Azure.

412 Erros de pré-condição ao usar um processador de eventos

412 Os erros de pré-condição ocorrem quando o cliente tenta assumir ou renovar a propriedade de uma partição, mas a versão local do registro de propriedade está desatualizada. Esse problema ocorre quando outra instância do processador rouba a propriedade da partição. Para obter mais informações, consulte a próxima seção.

A propriedade da partição muda frequentemente

Quando o número de EventProcessorClient instâncias muda (isto é, quando adicionas ou removes instâncias), as instâncias em execução tentam equilibrar as partições entre si. Durante alguns minutos após o número de processadores mudar, as partições mudam de proprietário. Depois de estar equilibrada, a propriedade das partições mantém-se estável e altera-se com pouca frequência. Se a propriedade das partições mudar frequentemente quando o número de processadores é constante, provavelmente indica um problema. Apresenta um problema no GitHub com registos e uma reprodução.

O CheckpointStore determina a posse da partição com base nos registos de posse. Em cada intervalo de balanceamento de carga, o EventProcessorClient executa as seguintes tarefas:

  1. Obtenha os registos de propriedade mais recentes.
  2. Verifique os registos para ver quais os registos que não atualizaram o seu carimbo temporal dentro do intervalo de expiração da propriedade da partição. Só são considerados os registos que correspondam a estes critérios.
  3. Se existirem partições não proprietárias e a carga não estiver equilibrada entre instâncias de EventProcessorClient, o cliente processador de eventos tenta reclamar uma partição.
  4. Atualize o registro de propriedade para as partições que ele possui que têm um link ativo para essa partição.

Você pode configurar o balanceamento de carga e os intervalos de expiração de propriedade ao criar o EventProcessorClient através do EventProcessorClientBuilder, conforme descrito na lista a seguir:

Por exemplo, se um registo de propriedade foi atualizado às 9h30 e partitionOwnershipExpirationInterval tem 2 minutos. Quando ocorre um ciclo de balanceamento de carga e nota que o registo de propriedade não é atualizado nos últimos 2 minutos ou até às 9:32 da manhã, considera a partição como não possuída.

Se ocorrer um erro num dos consumidores da partição, este fecha o consumidor correspondente, mas só tenta recuperá-lo no próximo ciclo de balanceamento de carga.

"... recetor atual '<RECEIVER_NAME>' com época '0' está sendo desconectado"

A mensagem de erro completa é semelhante à seguinte saída:

New receiver 'nil' with higher epoch of '0' is created hence current receiver 'nil' with epoch '0'
is getting disconnected. If you are recreating the receiver, make sure a higher epoch is used.
TrackingId:&lt;GUID&gt;, SystemTracker:&lt;NAMESPACE&gt;:eventhub:&lt;EVENT_HUB_NAME&gt;|&lt;CONSUMER_GROUP&gt;,
Timestamp:2022-01-01T12:00:00}"}

Este erro ocorre quando o balanceamento de carga ocorre após adicionar ou remover EventProcessorClient instâncias. O balanceamento de carga é um processo contínuo. Quando usa o BlobCheckpointStore com o seu consumidor, a cada ~30 segundos (por defeito), o consumidor verifica quais os consumidores que têm uma reclamação para cada partição. Depois, executa determinada lógica para determinar se necessita de 'roubar' uma partição de outro consumidor. O mecanismo de serviço usado para afirmar a propriedade exclusiva sobre uma partição é conhecido como a Época.

No entanto, se não estiveres a adicionar ou remover instâncias, existe um problema subjacente que deves resolver. Para obter mais informações, consulte a seção Mudanças frequentes de propriedade da partição e Problemas de arquivamento do GitHub.

Uso elevado de CPU

O uso elevado da CPU normalmente acontece porque uma instância possui demasiadas partições. Não ultrapasse três partições para cada núcleo de CPU. Comece com 1,5 partições para cada núcleo de CPU e depois teste aumentando o número de partições possuídas.

Sem memória e escolhendo o tamanho da pilha

O problema de falta de memória (OOM) pode ocorrer se o heap máximo atual da JVM for insuficiente para executar a aplicação. Poderá ser útil medir as necessidades de heap da aplicação. Em seguida, com base no resultado, dimensione a pilha definindo a memória máxima apropriada para o heap usando a opção JVM -Xmx.

Não especifique -Xmx como um valor maior do que a memória disponível ou limite definido para o host (a VM ou contentor) – por exemplo, a memória solicitada na configuração do contentor. Aloque memória suficiente para o host suportar o heap Java.

As etapas a seguir descrevem uma maneira típica de medir o valor para max Java Heap:

  1. Execute o aplicativo em um ambiente próximo à produção, onde o aplicativo envia, recebe e processa eventos sob a carga de pico esperada na produção.

  2. Aguarde até que a aplicação atinja um estado estacionário. Nesta fase, a aplicação e a JVM carregam todos os objetos de domínio, tipos de classe, instâncias estáticas, pools de objetos (TCP, pools de ligação de base de dados), e assim sucessivamente.

    No estado estacionário, você vê o padrão estável em forma de dente de serra para a coleção de pilha, conforme mostrado na captura de tela a seguir:

    Captura de ecrã da memória heap mostrando o padrão estável de dente de serra.

  3. Depois de a aplicação atingir um estado estável, force uma recolha completa de lixo (GC), utilizando ferramentas como o JConsole. Observe a memória ocupada após o GC completo. Você deseja dimensionar a pilha de modo que apenas 30% sejam ocupados após o GC completo. Use este valor para definir o tamanho máximo do heap (usando -Xmx).

Se estiveres a utilizar um contentor, dimensiona-o de modo a dispor de ~1 GB adicional de memória para a memória não heap da instância da JVM.

Cliente do processador para de receber

O cliente do processador geralmente é executado continuamente em um aplicativo host por dias a fio. Às vezes, ele percebe que EventProcessorClient não está processando uma ou mais partições. Normalmente, não há informação suficiente para determinar porque ocorreu a exceção. A EventProcessorClient parada é o sintoma de uma causa subjacente (ou seja, a condição de corrida) que ocorreu ao tentar se recuperar de um erro transitório. Para obter as informações necessárias, consulte Arquivando problemas do GitHub.

Duplo EventData recebido quando o processador é reiniciado

O serviço EventProcessorClient e Hubs de Eventos garante uma entrega ao menos uma vez. Você pode adicionar metadados para discernir eventos duplicados. Para obter mais informações, consulte Os Hubs de Eventos do Azure garantem uma entrega pelo menos uma vez? no Stack Overflow. Se precisar de uma entrega apenas uma vez, considere o Service Bus, que espera por um reconhecimento do cliente. Para obter uma comparação dos serviços de mensagens, consulte Escolhendo entre os serviços de mensagens do Azure.

Cliente consumidor de baixo nível deixa de receber

A biblioteca Event Hubs fornece o EventHubConsumerAsyncClient como um cliente de consumo de baixo nível. Foi concebido para utilizadores avançados que precisam de maior controlo e flexibilidade sobre as suas aplicações Reactive. Este cliente oferece uma interface de baixo nível, para que possa gerir o controlo da contrapressão, a gestão de threads e a recuperação na cadeia do Reactor. Ao contrário de EventProcessorClient, EventHubConsumerAsyncClient não inclui mecanismos de recuperação automática para todas as causas terminais. Por isso, deve gerir eventos terminais e selecionar operadores de Reator adequados para implementar estratégias de recuperação.

O EventHubConsumerAsyncClient::receiveFromPartition método emite um erro terminal quando a conexão encontra um erro não recuperável ou quando uma série de tentativas de recuperação de conexão falha consecutivamente, esgotando o limite máximo de repetição. Embora o recetor de baixo nível tente se recuperar de erros transitórios, espera-se que os usuários do cliente consumidor lidem com eventos de terminal. Se a receção contínua de eventos for desejada, a aplicação deve ajustar a cadeia do Reator para criar um novo cliente consumidor num evento terminal.

Migrar da biblioteca herdada para a nova biblioteca de cliente

O guia de migração inclui etapas sobre a migração do cliente herdado e a migração de pontos de verificação herdados.

Próximos passos

Se as orientações de resolução de problemas neste artigo não ajudarem a resolver problemas ao utilizar as bibliotecas de cliente do SDK do Azure para Java, submeta um problema no repositório do GitHub do SDK do Azure para Java.