Dimensionar seu aplicativo de processamento

Concluído

Para dimensionar seu aplicativo de processamento de eventos, você pode executar várias instâncias do aplicativo e fazer com que ele balancee a carga entre si. Nas versões mais antigas, EventProcessorHost permitia que você equilibrasse a carga entre várias instâncias do seu programa e criasse pontos de verificação dos eventos ao recebê-los. Nas versões mais recentes (5.0 em diante), o EventProcessorClient (.NET e Java) ou EventHubConsumerClient (Python e JavaScript) permite que você faça o mesmo.

Observação

O segredo para dimensionar os Hubs de Eventos é a ideia de consumidores particionados. Em contraste com o padrão de consumidores concorrentes, o padrão de consumidor particionado permite alta escala ao eliminar o gargalo de contenção e facilitar o paralelismo de ponta a ponta.

Cenário de exemplo

Como cenário de exemplo, considere uma empresa de segurança residencial que monitora 100.000 casas. A cada minuto, ele obtém dados de vários sensores, como um detector de movimento, sensor de porta/janela aberta, detector de quebra de vidro etc., instalado em cada residência. A empresa oferece um site para as residentes monitorarem a atividade da sua casa quase em tempo real.

Cada sensor envia dados para um hub de eventos. O hub de eventos é configurado com 16 partições. Na parte de consumo, você precisa de um mecanismo que possa ler esses eventos, consolidá-los e transferir a agregação para um blob de armazenamento, que é então exibido em uma página da web amigável ao usuário.

Ao projetar o consumidor em um ambiente distribuído, o cenário deve lidar com os seguintes requisitos:

  • Escala: criar vários consumidores, com cada consumidor assumindo a propriedade de leitura de algumas partições de Hubs de Eventos.
  • Balanceamento de carga: aumentar ou reduzir os consumidores dinamicamente. Por exemplo, quando um novo tipo de sensor (por exemplo, um detector de monóxido de carbono) é adicionado a cada casa, o número de eventos aumenta. Nesse caso, o operador (um ser humano) aumenta o número de instâncias de consumidor. Em seguida, o pool de consumidores pode rebalancear o número de partições que eles têm para compartilhar a carga com os consumidores recém-adicionados.
  • Resumo contínuo de falhas: se um consumidor (consumidor A) falhar (por exemplo, a máquina virtual que hospeda o consumidor falha repentinamente), outros consumidores devem poder selecionar as partições pertencentes ao consumidor A e continuar. Além disso, o ponto de continuação, chamado de ponto de verificação ou deslocamento, deve estar no ponto exato em que consumidor A falhou, ou um pouco antes disso.
  • Consumir eventos: embora os três pontos anteriores lidem com o gerenciamento do consumidor, deve haver código para consumir os eventos e fazer algo útil com eles. Por exemplo, agregá-lo e carregá-lo no armazenamento de blobs.

Processador de eventos ou cliente consumidor

Você não precisa criar sua própria solução para atender a esses requisitos. Os SDKs dos Hubs de Eventos do Azure fornecem essa funcionalidade. Em SDKs do .NET ou Java, você usa um cliente do processador de eventos (EventProcessorClient), e em SDKs de Python e JavaScript, você usa EventHubConsumerClient.

Para a maioria dos cenários de produção, recomendamos que você use o cliente do processador de eventos para ler e processar eventos. Os clientes do processador de eventos podem trabalhar de forma cooperativa no contexto de um grupo de consumidores para um determinado Hub de eventos. Os clientes gerenciarão automaticamente a distribuição e o balanceamento de trabalho, à medida que as instâncias ficam disponíveis ou indisponíveis para o grupo.

Controle de propriedade de partição

Uma instância do processador de eventos normalmente possui e processa eventos de uma ou mais partições. A propriedade de partições é distribuída uniformemente entre todas as instâncias do processador de eventos ativas associadas a uma combinação de Hub de eventos e grupo de consumidores.

Cada processador de eventos recebe um identificador exclusivo e a propriedade de declarações de partições ao adicionar ou atualizar uma entrada em um repositório de ponto de verificação. Todas as instâncias do processador de eventos se comunicam com esse repositório periodicamente para atualizar seu próprio estado de processamento e para saber mais sobre outras instâncias ativas. Esses dados são usados para balancear a carga entre os processadores ativos.

Receber mensagens

Ao criar um processador de eventos, especifique as funções que processam eventos e erros. Cada chamada para a função que processa eventos fornece um único evento de uma partição específica. É sua responsabilidade lidar com este evento. Caso queira garantir que o consumidor processe todas as mensagens pelo menos uma vez, você precisará escrever seu próprio código com a lógica de repetição. Mas tenha cuidado com as mensagens suspeitas.

É recomendável que você faça coisas de forma relativamente rápida. Ou seja, faça o mínimo de processamento possível. Caso você precise gravar no armazenamento e fazer algum roteamento, é melhor usar dois grupos de consumidores e ter dois processadores de evento.

Definindo o ponto de verificação

Marcação de ponto de verificação é um processo pelo qual um processador de eventos marca ou confirma a posição do último evento processado com sucesso em uma partição. A marcação de um ponto de verificação normalmente é feita dentro da função que processa os eventos e ocorre por partição dentro de um grupo de consumidores.

Se um processador de eventos se desconectar de uma partição, outra instância poderá retomar o processamento da partição no ponto de verificação que foi confirmado anteriormente pelo último processador dessa partição nesse grupo de consumidores. Quando o processador se conecta, ele passa esse deslocamento para o hub de eventos para especificar o local para começar a ler. Assim, você pode usar o ponto de verificação para marcar os eventos como "concluídos" por aplicativos de downstream e oferecer resiliência quando um processador de eventos ficar inativo. É possível retornar aos dados mais antigos, especificando um deslocamento inferior desse processo de ponto de verificação.

Instâncias de processador e acesso thread-safe

Por padrão, a função que processa os eventos é chamada sequencialmente para uma determinada partição. Os eventos e chamadas subsequentes para essa função a partir da mesma participação são enfileirados em segundo plano enquanto a bomba de eventos continua a ser executada em segundo plano em outros threads. Os eventos de partições diferentes podem ser processados simultaneamente e o estado compartilhado que seja acessado entre as partições deve ser sincronizado.