Hands On Kafka
Criando uma Rede Docker Comum a Todos os Serviços
Antes de tudo, vamos criar uma rede dentro do docker para que possamos reutilizá-la entre os nossos diferentes serviços que iremos subir. Para isso, execute:
docker network create kafka-hands-on
Subindo o Confluent Platform Stack
- Google: "kafka all in one"
- Comentar sobre as possibilidades de configurações
- Rodar o
docker-compose up
- Abir o Control Center: http://localhost:9021
- Mostrar um pouco da interface do Control Center
Tópicos
- Mostrar como cria um Tópico pela interface
- Criar um tópico manualmente e mostrar na interface:
docker-compose exec broker bash # kafka- (mostrar que existem vários comandos) kafka-topics --create --topic topico-exemplo --bootstrap-server localhost:9092
Consumindo e Produzindo
Sem partições
- Abrir uma nova aba de terminal
- Dividir a tela verticalmente (lado a lado)
- Na esquerda, dividir horizontalmente e iniciar dois consumers
docker-compose exec broker bash kafka-console-consumer --topic topico-exemplo --bootstrap-server localhost:9092
- Na direita, iniciar um producer sem uso de key (usar um pangrama)
docker-compose exec broker bash kafka-console-producer --topic topico-exemplo --bootstrap-server localhost:9092
- Comentar os comportamentos
- Mostrar as configurações do tópico:
kafka-topics --describe --topic topico-exemplo --bootstrap-server localhost:9092
- Mostrar essas configurações na interface
- Mostrar que as mensagens estão persistidas em disco, na interface: filtrar offset 0
Com partições
- Deletar o tópico criado:
kafka-topics --delete --topic topico-exemplo --bootstrap-server localhost:9092
- Criar novamente o tópico, agora com 2 partições:
kafka-topics --create --topic topico-exemplo --partitions 2 --bootstrap-server localhost:9092
- Vai dar erro, pq o tópico ainda existe. Ao produzir ou consumir em um tópico inexistente, o Kafka cria ele
- Parar os consumers
- Deleta e tenta criar outra vez. Se der erro, fecha o CP que ele pode ficar fazendo conexões
- Descrever o tópico criado e observar que agora existem duas partições:
kafka-topics --describe --topic topico-exemplo --bootstrap-server localhost:9092
- Reiniciar os dois consumers, do mesmo jeito anterior:
kafka-console-consumer --topic topico-exemplo --bootstrap-server localhost:9092
- Nada muda. Pare os consumers
Consumer Groups
- Agora silumando várias instâncias da mesma aplicacão (consumer groups):
kafka-console-consumer --topic topico-exemplo --group awesome-app --bootstrap-server localhost:9092 # do teclado pro seu coração
- Chamar atenção para o algoritmo Round-Robin
- Na direita, dividir horizontalmente
- Descrever os consumer groups no novo terminal:
kafka-consumer-groups --describe --group awesome-app --bootstrap-server localhost:9092
- Chamar atenção para o fato de cada partição ter um Consumer ID diferente
- Matar um dos consumers
- Descrever os consumer groups novamente:
kafka-consumer-groups --describe --group awesome-app --bootstrap-server localhost:9092
- Chamar atenção para o fato das partições terem um mesmo Consumer ID
- Mostrar nos LOGs da outra janela o processo de rebalancing acontecendo
- Publicar novas mensagens e observar que todas vão para o único consumer de pé:
# ela roda a cidade inteira pra ficar comigo
- Subir novamente o consumidor que tinha caído
- Publicar novas mensagens e observar que o rebalanceamento foi feito:
# eu sou seu esquema preferido # ela dispensa a balada, as amigas, pra ficar comigo
- Descrever o consumer group e observar que os Consumer IDs são distintos novamente:
kafka-consumer-groups --describe --group awesome-app --bootstrap-server localhost:9092
- Subindo um novo consumer, na esperança de ir mais rápido. Produzir novas mensagens
kafka-console-consumer --topic topico-exemplo --group awesome-app --bootstrap-server localhost:9092 # é só tu ligar pra mim que eu não resisto
Usando Chaves
- Produzindo com chaves:
kafka-console-producer --topic topico-exemplo --bootstrap-server localhost:9092 --property parse.key=true --property key.separator=:
Integrando Kafka em Aplicações
Consumer em Go
Documentação da Biblioteca da Confluent
Documentação de Configurações dos Consumers
- Subir inicialmente tentando se comunicar com a porta errada (
9092
) antes de usar a certa (29092
) - Mostrar que não é possível subir sem informar o
group.id
- Mostrar que é possível consumir um ou vários tópicos:
.Subscribe()
ou.SubscribeTopics()
- Produzir várias mensagens em um tópico particionado e observar que o consumo será meio bagunçado
- Mostrar as diferenças entre as opções de
earliest
elatest
do reset do offset - Encerrar o consumidor, produzir mensagens, voltar com ele e observar que continua onde parou
- Mostrar o uso de expressão regular no subscribe
Producer em PHP
Documentação da Biblioteca Laravel Kafka
Documentação da Biblioteca librdkafka em C
- Explicar o conteúdo do arquivo
api.php
e pastamigrations
- Mostrar o
docker-compose.yml
- Interagir com a API de cadastro de filmes
- Mostrar que os registros foram salvos na base de dados
- Mostrar que o consumer em Go e no console, recebem os eventos do tópico
Comandos Úteis
# Executar obrigatoriamente
cp .env.example .env
docker-compose build
docker run -it --rm --name php-producer-app -v $(pwd):/var/www/html php-producer-app composer install
docker run -it --rm --name php-producer-app -v $(pwd):/var/www/html php-producer-app php artisan key:generate
docker-compose up
docker-compose exec app sh
php artisan migrate
# Requisições para a API
http POST http://localhost:8000/api title="Forrest Gump" release_year=1994 description="Um cara que conta historias"
http POST http://localhost:8000/api title="The Shawshank Redemption" release_year=1994
# Caso seja preciso acessar o app
docker-compose exec app sh
# Caso seja preciso acessar a database e fazer mudanças
docker-compose exec db mysql -u root
UPDATE films SET title = 'Big Hero 6', release_year = 2014, description = 'Uma animacao daora' where id = 1;
Connectors
Source Connector - MySQL
- Comentar sobre o esquema de Source Connector e Sink Connectors
- Mostrar na interface da Confluent Platform onde fica o Kafka Connect
- Mostrar que as opções aparecem pois no
docker-compose.yml
foi feita a instalação - Mostrar a criação pela interface
- Mostrar o JSON do source connector do MySQL
- Importar o source connector do MySQL pela interface:
\\wsl$\Ubuntu-20.04\home\claudson\Code\kafka-hands-on\src\connectors
- Mostrar os tópicos criados pelo Connect
- Mostrar o campo
op
nos tópico da tabelafilms
, que representa o tipo de operação:c = create; d = delete; u = update
- Fazer um update na base de dados, e mostrar que isso cairá nos tópicos
- Mostrar como ele obtém as informações
- Não é ficar fazendo
SELECT * FROM
- Mostrar que é sobrescrito o comando de inicialização do mysql no
docker-compose.yml
para habilitar os logs binários
- Não é ficar fazendo
Sink Connector - MongoDB
- Mostrar o JSON do sink para o MongoDB
- Explicar as configurações.
- Transformação vai fazer uma extração (
ExtractField
), do campoafter
- Abrir o link das transformações para ver as opções
- Transformação vai fazer uma extração (
- Entrar no mongo e ver os registros salvos
Interagindo com o MongoDB
docker-compose exec mongodb mongo --username root --password
use reports
show collections
db.films.find()
Possíveis Dúvidas
Preciso de um acompanhamento/monitoramento constante para garantir que o processo do broker está rodando no docker?
Você geralmente não vai rodar o Kafka com Docker. Talvez um serviço gerenciado ou no bare metal. Mínimo de 3 máquinas (brokers) no cluster.
Existe um controlador do Kafka para o Kubernetes, é um caminho possível, mas geralmente um serviço autogerenciado ou você subir suas máquinas e configurar o Kafka é mais comum.
Qual o Use Case dos Consumer Groups?
Distribuir o processamento das mensagens. Aumentar o throughput da leitura das mensagens.
Qual a fórmula para definir o número de partições de um tópico?
Choosing the number of partitions for a topic
- is the number of required producers determined by calculating:
- is the number of required consumers determined by calculating:
- is the total expected throughput for our system
- is the max throughput of a single producer to a single partition
- is the max throughput of a single consumer from a single partition