Partilhar via


Otimização de desempenho para clusters Apache Kafka HDInsight

Este artigo fornece algumas sugestões para otimizar o desempenho de suas cargas de trabalho do Apache Kafka no HDInsight. O foco está em ajustar a configuração do produtor, do intermediário e do consumidor. Às vezes, você também precisa ajustar as configurações do sistema operacional para ajustar o desempenho com carga de trabalho pesada. Existem diferentes maneiras de medir o desempenho, e as otimizações que você aplica dependem das necessidades do seu negócio.

Visão geral da arquitetura

Os tópicos de Kafka são usados para organizar registros. Os produtores produzem discos e os consumidores consomem-nos. Os produtores enviam registros para os corretores Kafka, que armazenam os dados. Cada nó de trabalho no cluster HDInsight é um mediador Kafka.

Registos de partição de tópicos em mediadores. Ao consumir registos, pode utilizar até um consumidor por partição para obter processamento paralelo dos dados.

A replicação é usada para duplicar partições entre nós. Esta partição protege contra interrupções de nó (corretor). Uma única partição no grupo de réplicas é designada como líder da partição. O tráfico do produtor é encaminhado para o líder de cada nó mediante a utilização do estado gerido pelo ZooKeeper.

Identifique o seu cenário

O desempenho do Apache Kafka tem dois aspetos principais – taxa de transferência e latência. A taxa de transferência é a taxa máxima na qual os dados podem ser processados. Maior rendimento é melhor. Latência é o tempo necessário para que os dados sejam armazenados ou recuperados. Menor latência é melhor. Encontrar o equilíbrio certo entre taxa de transferência, latência e o custo da infraestrutura do aplicativo pode ser um desafio. Seus requisitos de desempenho devem corresponder a uma das três situações comuns a seguir, com base na necessidade de alta taxa de transferência, baixa latência ou ambas:

  • Alta taxa de transferência, baixa latência. Este cenário requer alta taxa de transferência e baixa latência (~100 milissegundos). Um exemplo desse tipo de aplicativo é o monitoramento de disponibilidade de serviço.
  • Alta taxa de transferência, alta latência. Este cenário requer alta taxa de transferência (~1,5 GBps), mas pode tolerar latência mais alta (< 250 ms). Um exemplo desse tipo de aplicação é a ingestão de dados de telemetria para processos quase em tempo real, como aplicativos de segurança e deteção de intrusão.
  • Baixa taxa de transferência, baixa latência. Este cenário requer baixa latência (< 10 ms) para processamento em tempo real, mas pode tolerar uma taxa de transferência mais baixa. Um exemplo deste tipo de aplicação são as verificações ortográficas e gramaticais online.

Configurações do produtor

As seções a seguir destacam algumas das propriedades de configuração genérica mais importantes para otimizar o desempenho de seus produtores de Kafka. Para obter uma explicação detalhada de todas as propriedades de configuração, consulte a documentação do Apache Kafka sobre configurações do produtor.

Tamanho do lote

Os produtores do Apache Kafka montam grupos de mensagens (chamadas lotes) que são enviadas como uma unidade para serem armazenadas em uma única partição de armazenamento. Tamanho do lote significa o número de bytes que devem estar presentes antes que esse grupo seja transmitido. Aumentar o batch.size parâmetro pode aumentar a taxa de transferência, uma vez que reduz a sobrecarga de processamento de solicitações de rede e E/S. Sob carga leve, o aumento do tamanho do lote pode aumentar a latência de envio de Kafka enquanto o produtor espera que um lote esteja pronto. Sob carga pesada, recomenda-se aumentar o tamanho do lote para melhorar a taxa de transferência e a latência.

Agradecimentos exigidos pelo produtor

A configuração do produtor acks necessária determina o número de confirmações exigidas pelo líder da partição antes que uma solicitação de gravação seja considerada concluída. Essa configuração afeta a confiabilidade dos dados e usa valores de 0, 1ou -1. O valor de -1 significa que uma confirmação deve ser recebida de todas as réplicas, antes que a gravação seja concluída. A configuração acks = -1 fornece garantias mais fortes contra perda de dados, mas também resulta em maior latência e menor taxa de transferência. Se os requisitos do seu aplicativo exigirem uma taxa de transferência mais alta, tente definir acks = 0 ou acks = 1. Lembre-se de que não reconhecer todas as réplicas pode reduzir a confiabilidade dos dados.

Compressão

Um produtor Kafka pode ser configurado para compactar mensagens antes de enviá-las aos corretores. A compression.type configuração especifica o codec de compactação a ser usado. Os codecs de compressão suportados são "gzip", "snappy" e "lz4". A compressão é benéfica e deve ser considerada se houver uma limitação na capacidade do disco.

Entre os dois codecs de compressão comumente usados, gzip e snappy, gzip tem uma taxa de compressão mais alta, o que resulta em menor uso de disco ao custo de maior carga da CPU. O snappy codec fornece menos compressão com menos sobrecarga de CPU. Você pode decidir qual codec usar com base nas limitações do disco do broker ou da CPU do produtor. gzip É capaz de comprimir dados a uma taxa cinco vezes superior à do snappy.

A compactação de dados aumenta o número de registros que podem ser armazenados em um disco. Também pode aumentar a sobrecarga da CPU nos casos em que há uma incompatibilidade entre os formatos de compressão que estão sendo usados pelo produtor e pelo corretor. como os dados devem ser compactados antes do envio e, em seguida, descompactados antes do processamento.

Configurações do corretor

As seções a seguir destacam algumas das configurações mais importantes para otimizar o desempenho de seus corretores Kafka. Para obter uma explicação detalhada de todas as configurações do broker, consulte a documentação do Apache Kafka sobre configurações do broker.

Número de discos

Os discos de armazenamento têm IOPS (operações de entrada/saída por segundo) limitadas e bytes de leitura/gravação por segundo. Ao criar novas partições, Kafka armazena cada nova partição no disco com o menor número de partições existentes para equilibrá-las entre os discos disponíveis. Apesar da estratégia de armazenamento, ao processar centenas de réplicas de partição em cada disco, o Kafka pode facilmente saturar a taxa de transferência de disco disponível. A compensação aqui é entre taxa de transferência e custo. Se seu aplicativo exigir maior taxa de transferência, crie um cluster com mais discos gerenciados por broker. Atualmente, o HDInsight não oferece suporte à adição de discos gerenciados a um cluster em execução. Para obter mais informações sobre como configurar o número de discos gerenciados, consulte Configurar armazenamento e escalabilidade para Apache Kafka no HDInsight. Compreenda as implicações de custo do aumento do espaço de armazenamento para os nós em seu cluster.

Número de tópicos e partições

Os produtores do Kafka escrevem em tópicos. Os consumidores de Kafka leem a partir de tópicos. Um tópico está associado a um log, que é uma estrutura de dados no disco. Kafka acrescenta registros de um produtor (s) ao final de um log de tópicos. Um journal de tópicos consiste em muitas partições distribuídas por vários ficheiros. Esses arquivos, por sua vez, estão espalhados por vários nós de cluster Kafka. Os consumidores leem os tópicos de Kafka ao seu ritmo e podem escolher a sua posição no registo de tópicos.

Cada partição Kafka é um arquivo de log no sistema, e os threads do produtor podem gravar em vários logs simultaneamente. De modo semelhante, visto que cada thread de consumidor é responsável por ler mensagens de uma única partição, o consumo de várias partições é também gerido em paralelo.

Aumentar a densidade da partição (o número de partições por broker) adiciona uma sobrecarga relacionada às operações de metadados e por solicitação/resposta de partição entre o líder da partição e seus seguidores. Mesmo na ausência de fluxo de dados, as réplicas de partição ainda buscam dados dos líderes, o que resulta em processamento extra para enviar e receber solicitações pela rede.

Para clusters Apache Kafka 2.1 e 2.4 e como observado anteriormente no HDInsight, recomendamos que você tenha um máximo de 2000 partições por broker, incluindo réplicas. Aumentar o número de partições por corretor diminui a taxa de transferência e também pode ocasionar indisponibilidade do tópico. Para obter mais informações sobre o suporte à partição Kafka, consulte a postagem oficial do blog Apache Kafka sobre o aumento no número de partições suportadas na versão 1.1.0. Para obter detalhes sobre como modificar tópicos, consulte Apache Kafka: modificando tópicos.

Número de réplicas

Um fator de replicação mais alto resulta em solicitações adicionais entre o líder da partição e os seguidores. Consequentemente, um fator de replicação maior consome mais disco e CPU para lidar com solicitações adicionais, aumentando a latência de gravação e diminuindo a taxa de transferência.

Recomendamos que você use pelo menos a replicação 3x para Kafka no Azure HDInsight. A maioria das regiões do Azure tem três domínios de falha, mas em regiões com apenas dois domínios de falha, os usuários devem usar a replicação 4x.

Para obter mais informações sobre replicação, consulte Apache Kafka: replicação e Apache Kafka: aumentando o fator de replicação.

Configurações do consumidor

A seção a seguir destaca algumas configurações genéricas importantes para otimizar o desempenho de seus consumidores Kafka. Para obter uma explicação detalhada de todas as configurações, consulte a documentação do Apache Kafka sobre configurações de consumidor.

Número de consumidores

É uma boa prática ter o número de partições igual ao número de consumidores. Se o número de consumidores for menor do que o número de partições, alguns dos consumidores leem de várias partições, aumentando a latência do consumidor.

Se o número de consumidores for maior do que o número de partições, então você está desperdiçando seus recursos de consumo, uma vez que esses consumidores estão ociosos.

Evitar o reequilíbrio frequente do consumidor

O reequilíbrio do consumidor é desencadeado pela mudança de propriedade da partição (ou seja, o aumento ou diminuição do número de consumidores), uma falha do corretor (pois os corretores são coordenadores de grupos de consumidores), uma falha do consumidor, a adição de um novo tópico ou novas partições. Durante o reequilíbrio, os consumidores não podem consumir, aumentando assim a latência.

Os consumidores são considerados vivos se ele pode enviar um batimento cardíaco para um corretor dentro de session.timeout.ms. Caso contrário, o consumidor é considerado morto ou falhado. Este atraso conduz a um reequilíbrio dos consumidores. Quanto menor o consumidor session.timeout.ms, mais rápido podemos detetar essas falhas.

Se o session.timeout.ms for muito baixo, um consumidor pode experimentar repetidos reequilíbrios desnecessários, devido a cenários como quando um lote de mensagens demora mais a ser processado ou quando uma pausa de GC da JVM demora muito tempo. Se tiver um consumidor que gasta muito tempo a processar mensagens, pode resolver isso aumentando o limite máximo do tempo que um consumidor pode ficar inativo antes de buscar mais registos com max.poll.interval.ms ou reduzindo o tamanho máximo dos lotes retornados com o parâmetro de configuração max.poll.records.

Criação de batches

Como os produtores, podemos adicionar lotes para os consumidores. A quantidade de dados que os consumidores podem obter em cada solicitação de busca pode ser configurada alterando a configuração fetch.min.bytes. Este parâmetro define os bytes mínimos esperados de uma resposta de busca de um consumidor. Aumentar esse valor reduz o número de solicitações de busca feitas ao corretor, reduzindo assim a sobrecarga extra. Por padrão, esse valor é 1. Da mesma forma, há outra configuração fetch.max.wait.ms. Se uma solicitação de busca não tiver mensagens suficientes de acordo com o tamanho de fetch.min.bytes, ela aguardará até a expiração do tempo de espera com base nesta configuração fetch.max.wait.ms.

Observação

Em poucos cenários, os consumidores podem parecer lentos, quando não conseguem processar a mensagem. Se você não estiver cometendo a compensação após uma exceção, o consumidor ficará preso a uma compensação específica em um loop infinito e não avançará, aumentando o atraso do lado do consumidor como resultado.

Ajuste do sistema operacional Linux com carga de trabalho pesada

Mapas de memória

vm.max_map_count Define o número máximo de MMAP que um processo pode ter. Por padrão, no HDInsight Apache Kafka cluster linux VM, o valor é 65535.

No Apache Kafka, cada segmento de log requer um par de arquivos index/timeindex, e cada um desses arquivos consome um mmap. Em outras palavras, cada segmento de log usa dois mmap. Assim, se cada partição hospedar um único segmento de log, são necessários no mínimo dois mmap. O número de segmentos de log por partição varia dependendo do tamanho do segmento, intensidade de carga, política de retenção, período contínuo e, geralmente, tende a ser mais de um. Mmap value = 2*((partition size)/(segment size))*(partitions)

Se o valor mmap necessário exceder o vm.max_map_count, o broker gerará a exceção "Map failed".

Para evitar essa exceção, use os comandos abaixo para verificar o tamanho do mmap na vm e aumentar o tamanho, se necessário, em cada nó de trabalho.

# command to find number of index files:
find . -name '*index' | wc -l

# command to view vm.max_map_count for a process:
cat /proc/[kafka-pid]/maps | wc -l

# command to set the limit of vm.max_map_count:
sysctl -w vm.max_map_count=<new_mmap_value>

# This will make sure value remains, even after vm is rebooted:
echo 'vm.max_map_count=<new_mmap_value>' >> /etc/sysctl.conf
sysctl -p

Observação

Tenha cuidado ao definir isso muito alto, pois ele ocupa memória na VM. A quantidade de memória permitida para ser usada pela JVM em mapas de memória é determinada pela configuração MaxDirectMemory. O valor padrão é 64MB. É possível que isso seja alcançado. Você pode aumentar esse valor adicionando -XX:MaxDirectMemorySize=amount of memory used às configurações da JVM por meio do Ambari. Esteja ciente da quantidade de memória que está sendo usada no nó e se há RAM disponível suficiente para suportar isso.

Próximos passos