Partilhar via


Otimização de desempenho para os clusters do HDInsight no Apache Kafka

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, corretor e 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.

Descriçã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. Quando consumir registos, pode utilizar até um consumidor por partição para alcançar o processamento paralelo dos dados.

A replicação é usada para duplicar partições entre nós. Esta partição protege contra interrupções de nó (broker). Uma única partição entre o 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.

Identificar 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 parâmetro pode aumentar a batch.size taxa de transferência, porque 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 necessária acks do produtor 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 significa que uma confirmação deve ser recebida de todas as réplicas antes que -1 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, e snappy, tem uma taxa de compressão mais alta, gzip gzip 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 da CPU do disco do broker ou do produtor. gzipÉ capaz de comprimir dados a uma taxa cinco vezes superior à .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, 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 de Kafka escrevem para 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 log de tópicos consiste em muitas partições que estão espalhadas por vários arquivos. Esses arquivos, por sua vez, estão espalhados por vários nós de cluster Kafka. Os consumidores leem os tópicos de Kafka em sua cadência e podem escolher sua posição (offset) no log 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. Da mesma forma, como cada thread de consumidor lê mensagens de uma partição, o consumo de várias partições também é tratado 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 broker diminui a taxa de transferência e também pode causar 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, os consumidores aumentam ou diminuem), uma falha do corretor (já que os corretores são coordenadores de grupo para grupos de consumidores), uma falha do consumidor, adicionando um novo tópico ou adicionando 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 falido. 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 for session.timeout.ms muito baixo, um consumidor pode experimentar repetidos reequilíbrios desnecessários, devido a cenários como quando um lote de mensagens leva mais tempo para ser processado ou quando uma pausa de GC da JVM leva muito tempo. Se você tiver um consumidor que gasta muito tempo processando mensagens, poderá resolver isso aumentando o limite superior da quantidade de tempo que um consumidor pode ficar ocioso antes de buscar mais registros ou max.poll.interval.ms reduzindo o tamanho máximo dos lotes retornados com o parâmetro max.poll.recordsde configuração .

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 do , ela aguardará até a expiração do tempo de fetch.min.bytesespera com base nessa configuração fetch.max.wait.ms.

Nota

Em poucos cenários, os consumidores podem parecer lentos, quando não conseguem processar a mensagem. Se você não estiver cometendo o offset após uma exceção, o consumidor ficará preso em um determinado offset 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 hospeda um único segmento de log, ele requer 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 , o broker gerará a vm.max_map_countexceçã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

Nota

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