Compartilhar via


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

Este artigo fornece soluções para problemas comuns que você pode encontrar ao usar o EventProcessorClient tipo. Se você estiver procurando soluções para outros problemas comuns que você pode encontrar ao usar os Hubs de Eventos do Azure, consulte Solucionar problemas dos Hubs de Eventos do Azure.

412 erros de pré-condição ao utilizar um processador de eventos

412 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 secção seguinte.

A propriedade da partição muda com frequência

Quando o número de EventProcessorClient instâncias é alterado (ou seja, são adicionados ou removidos), as instâncias em execução tentam balancear a carga de partições entre si. Por alguns minutos após o número de processadores mudar, as partições devem mudar de proprietário. Uma vez balanceada, a propriedade da partição deve permanecer estável e mudar com pouca frequência. Se a propriedade da partição estiver mudando com frequência quando o número de processadores for constante, provavelmente indicará um problema. Recomendamos que você registre um problema do GitHub com logs e uma reprodução.

A propriedade da partição é determinada pelos registros de propriedade no CheckpointStore. Em cada intervalo de balanceamento de carga, o EventProcessorClient executará as seguintes tarefas:

  1. Busque os registros de propriedade mais recentes.
  2. Verifique os registros para ver quais registros não atualizaram o timestamp dentro do intervalo de expiração da propriedade da partição. Somente registros que correspondem a esses critérios são considerados.
  3. Se houver partições não atribuídas e a carga não for balanceada entre instâncias de EventProcessorClient, o cliente do processador de eventos tentará reivindicar uma partição.
  4. Atualize o registro de propriedade das partições que possui que têm um link ativo para essa partição.

Você pode configurar os intervalos de balanceamento de carga e expiração de propriedade ao criar o EventProcessorClient por meio do EventProcessorClientBuilder, conforme descrito na seguinte lista:

Por exemplo, se um registro de propriedade foi atualizado às 9h30 e partitionOwnershipExpirationInterval representa 2 minutos. Quando ocorrer um ciclo de balanceamento de carga e ele perceber que o registro de propriedade não foi atualizado nos últimos 2 minutos ou até as 9h32, considerará a partição como não possuída.

Se ocorrer um erro em um dos consumidores de partição, ele fechará o consumidor correspondente, mas não tentará recuperá-lo até o próximo ciclo de balanceamento de carga.

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

A mensagem de erro inteira é 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}"}

Esse erro é esperado quando o balanceamento de carga ocorre depois que EventProcessorClient instâncias são adicionadas ou removidas. O balanceamento de carga é um processo contínuo. Quando você usa o BlobCheckpointStore com seu consumidor, a cada ~30 segundos (por padrão), o consumidor verifica quais consumidores têm uma reivindicação para cada partição e, em seguida, executa um processo lógico para determinar se é necessário 'roubar' uma partição de outro consumidor. O mecanismo de serviço usado para afirmar a propriedade exclusiva sobre uma partição é conhecido como Época.

No entanto, se nenhuma instância estiver sendo adicionada ou removida, haverá um problema subjacente que deve ser resolvido. Para obter mais informações, consulte a seção A propriedade da partição muda com frequência e Registrar problemas do GitHub.

Alto uso da CPU

O alto uso da CPU geralmente ocorre porque uma instância possui muitas partições. Recomendamos não mais do que três partições para cada núcleo de CPU. É melhor começar com 1,5 partição para cada núcleo de CPU e, em seguida, testar aumentando o número de partições com propriedade.

Sem memória e escolhendo o tamanho do heap

O problema de memória insuficiente (OOM) pode acontecer se o heap máximo atual da JVM for insuficiente para executar o aplicativo. Talvez você queira medir o requerimento de heap do aplicativo. Em seguida, com base no resultado, dimensione o heap definindo a memória máxima apropriada do heap usando a opção JVM -Xmx.

Você não deve especificar -Xmx como um valor maior do que a memória disponível ou o limite definido para o host (a VM ou contêiner) – por exemplo, a memória solicitada na configuração do contêiner. Você deve alocar memória suficiente para o host dar suporte ao heap Java.

As etapas a seguir descrevem uma maneira típica de medir o valor do Heap Java máximo:

  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 o aplicativo atinja um estado estável. Neste estágio, o aplicativo e a JVM teriam carregado todos os objetos de domínio, tipos de classe, instâncias estáticas, pools de objetos (TCP, pools de conexões de BD), etc.

    No estado estável, você verá o padrão estável serrilhado para a coleção de heap, conforme mostrado na seguinte captura de tela:

    Captura de tela da coleção de memória de heap mostrando o padrão estável serrilhado.

  3. Depois que o aplicativo atingir o estado estável, force uma GC (coleta de lixo) completa usando ferramentas como JConsole. Observe a memória ocupada após o GC completo. Você deseja dimensionar o heap de modo que apenas 30% sejam ocupados após o GC completo. Você pode usar esse valor para definir o tamanho máximo do heap (usando -Xmx).

Se você estiver no contêiner, dimensione o contêiner para ter ~1 GB extra de memória para a necessidade de não heap para a instância de JVM.

O 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ções suficientes para determinar por que a exceção ocorreu. A parada EventProcessorClient é 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 Arquivar problemas do GitHub.

Dados do evento duplicados recebidos quando o processador é reiniciado

O serviço EventProcessorClient e Hubs de Eventos garante uma entrega pelo 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 você precisar de entrega única, deverá considerar o Barramento de Serviço, que aguarda uma confirmação do cliente. Para obter uma comparação dos serviços de mensagens, consulte Escolhendo entre os serviços de mensagens do Azure.

Cliente de consumidor de baixo nível para de receber

EventHubConsumerAsyncClient é um cliente de consumidor de baixo nível fornecido pela biblioteca de Hubs de Eventos, projetado para usuários avançados que exigem maior controle e flexibilidade sobre seus aplicativos reativos. Esse cliente oferece uma interface de baixo nível, permitindo que os usuários gerenciem backpressure, threading e recuperação dentro da cadeia reator. Ao contrário de EventProcessorClient, EventHubConsumerAsyncClient não inclui mecanismos de recuperação automática para todas as causas terminais. Portanto, os usuários devem lidar com eventos de terminal e selecionar operadores de reator apropriados para implementar estratégias de recuperação.

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

Migrar da biblioteca de clientes herdada para a nova

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

Próximas etapas

Se as diretrizes de solução de problemas neste artigo não ajudarem a resolver problemas quando você usa o SDK do Azure para bibliotecas de clientes Java, recomendamos que você registre um problema no repositório GitHub do Azure SDK para Java.