Balancear a carga de partição entre várias instâncias do seu aplicativo

Para escalonar seu aplicativo de processamento de eventos, você pode executar várias instâncias do aplicativo e equilibrar a carga entre si. Nas versões mais antigas, o EventProcessorHost permitia que você balanceasse a carga entre várias instâncias do programa e eventos de ponto de verificação ao receber os eventos. Nas versões mais recentes (5.0 em diante), EventProcessorClient (.NET e Java) ou EventHubConsumerClient (Python e JavaScript) permite que você faça o mesmo. O modelo de desenvolvimento é simplificado com o uso de eventos. Você assina os eventos nos quais está interessado registrando um manipulador de eventos. Se você estiver usando a versão antiga da biblioteca de cliente, consulte os seguintes guias de migração: .NET, Java, Pythone JavaScript.

Este artigo descreve um cenário de exemplo para usar várias instâncias de aplicativos cliente para ler eventos de um hub de eventos. Ele também fornece detalhes sobre os recursos do cliente do processador de eventos, que permite receber eventos de várias partições ao mesmo tempo e balancear a carga com outros consumidores que usam o mesmo grupo de consumidores e de hub de eventos.

Observação

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

Cenário de exemplo

Como um cenário de exemplo, considere uma empresa de segurança inicial que monitora 100.000 residências. 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 da web para 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. No lado do consumidor, você precisa de um mecanismo que possa ler esses eventos, consolidá-los (filtrar, agregar, etc.) e despejar o agregado em um blob de armazenamento, que é então projetado para uma página da web amigável.

Aplicativo do consumidor

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

  1. Escala: criar vários consumidores, com cada consumidor assumindo a propriedade de leitura de algumas partições de Hubs de eventos.
  2. O 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 página inicial, aumenta o número de eventos. Nesse caso, o operador (um ser humano) aumenta o número de instâncias de consumidor. Em seguida, o pool de consumidores pode redistribuir o número de partições que são proprietárias, para compartilhar a carga com os consumidores recém-adicionados.
  3. Retorno 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 de propriedade do consumidor A e continuar. Além disso, o ponto de continuação, chamado de checkpoint ou offset, deve estar no ponto exato em que consumidor A falhou, ou um pouco antes disso.
  4. Consumir eventos: enquanto os três pontos anteriores lidam com o gerenciamento do consumidor, deve haver código para consumir os eventos e fazer algo útil com ele. 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. Na versão antiga do SDK, era o host do processador de eventos (EventProcessorHost) que suportava esses recursos.

Para a maioria dos cenários de produção, recomendamos que você use o cliente do processador de eventos para ler e processar eventos. O cliente de processador destina-se a fornecer uma experiência robusta para o processamento de eventos em todas as partições de um hub de eventos de maneira eficaz e tolerante a falhas, fornecendo um meio de ponto de verificação do seu progresso. 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.

Propriedade da 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 de 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. Novas instâncias podem ingressar no pool de processamento para escalar verticalmente. Quando as instâncias ficam inativas, devido a falhas ou para reduzir verticalmente, a propriedade da partição é transferida normalmente para outros processadores ativos.

Os registros de propriedade de partição no repositório de ponto de verificação controlam o namespace dos hubs de eventos, o nome do hub de eventos, o grupo de consumidores, o identificador do processador de eventos (também conhecido como proprietário), a ID da partição e a hora da última modificação.

Namespace do Hubs de Eventos Nome do Hub de Eventos Grupo de consumidores Proprietário Partition ID Hora da última modificação
mynamespace.servicebus.windows.net myeventhub myconsumergroup 3be3f9d3-9d9e-4c50-9491-85ece8334ff6 0 2020-01-15T01:22:15
mynamespace.servicebus.windows.net myeventhub myconsumergroup f5cc5176-ce96-4bb4-bbaa-a0e3a9054ecf 1 2020-01-15T01:22:17
mynamespace.servicebus.windows.net myeventhub myconsumergroup 72b980e9-2efc-4ca7-ab1b-ffd7bece8472 2 2020-01-15T01:22:10
:
:
mynamespace.servicebus.windows.net myeventhub myconsumergroup 844bd8fb-1f3a-4580-984d-6324f9e208af 15 2020-01-15T01:22:00

Cada instância do processador de eventos adquire a propriedade de uma partição e começa a processar a partição do último ponto de verificaçãoconhecido. Se um processador falhar (a VM é desligada), outras instâncias o detectam examinando a hora da última modificação. Outras instâncias tentam obter a propriedade das partições anteriormente pertencentes à instância inativa. O repositório de ponto de verificação garante que apenas uma das instâncias tenha êxito ao declarar a propriedade de uma partição. Portanto, em qualquer dado momento, há no máximo um processador que recebe eventos de uma partição.

Receber mensagens

Ao criar um processador de eventos, você especifica funções que processarão eventos e erros. Cada chamada para a função que processa eventos fornece um único evento de uma partição específica. Ele é responsável por gerenciar o estes eventos. Caso deseje garantir que o consumidor processe todas as mensagens pelo menos uma vez, você precisará escrever seu próprio código com lógica de repetição. Mas tenha cuidado com mensagens suspeitas.

É recomendável que você faça coisas de forma relativamente rápida. Ou seja, faça o menor 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.

Ponto de verificação

Pontos de verificação é um processo pelo qual um processador de eventos marca ou confirma a posição do último evento processado com êxito em uma partição. Marcar um ponto de verificação normalmente é feito dentro da função que processa os eventos e ocorre em uma base 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 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.

Quando o ponto de verificação é executado para marcar um evento como processado, uma entrada no repositório de ponto de verificação é adicionada ou atualizada com o deslocamento e o número de sequência do evento. Os usuários devem decidir a frequência de atualização do ponto de verificação. A atualização após cada evento processado com êxito pode ter implicações de desempenho e custo, pois dispara uma operação de gravação para o repositório de ponto de verificação subjacente. Além disso, a definição de ponto de verificação para cada evento é indicativo de um padrão de mensagens enfileiradas para o qual uma fila do barramento de serviço pode ser uma opção melhor do que um hub de eventos. A ideia por trás dos Hubs de eventos é que você obtenha entregas "pelo menos uma vez" em grande escala. Ao tornar seus sistemas downstream idempotentes, é fácil se recuperar de falhas ou reinicializações que resultam nos mesmos eventos sendo recebidos várias vezes.

Siga estas recomendações ao usar Armazenamento de Blobs do Azure como um repositório de ponto de verificação:

  • Use um contêiner separado para cada grupo de consumidores. Você pode usar a mesma conta de armazenamento, mas usar um contêiner por cada grupo.
  • Não use o contêiner para mais nada e não use a conta de armazenamento para mais nada.
  • A conta de armazenamento deve estar na mesma região em que o aplicativo implantado está localizado. Se o aplicativo for local, tente escolher a região mais próxima possível.

Na página Conta de armazenamento do portal do Azure, na seção serviço Blob, verifique se as seguintes configurações estão desabilitadas.

  • Namespace hierárquico
  • Exclusão temporária de blobs
  • Controle de versão

Instâncias de processador e de segurança do thread

Por padrão, a função que processa 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 qualquer estado compartilhado que seja acessado entre partições deve ser sincronizado.

Próximas etapas

Consulte o seguinte início rápido: