No design moderno do sistema, a Arquitetura Orientada a Eventos (EDA) foca em criar, detectar, usar e responder a eventos dentro de um sistema. Eventos são ocorrências significativas que podem afetar o hardware ou software de um sistema, como ações do usuário, mudanças de estado ou atualizações de dados.
A EDA permite que diferentes partes de uma aplicação interajam de forma desacoplada, permitindo que se comuniquem por meio de eventos em vez de chamadas diretas. Essa configuração permite que os componentes trabalhem de forma independente, respondam a eventos de forma assíncrona e se ajustem às necessidades comerciais em constante mudança sem reconfiguração significativa do sistema, promovendo agilidade.
Novas e aplicações modernas agora dependem fortemente do processamento de dados em tempo real e da responsividade. A importância da EDA não pode ser subestimada, pois ela fornece o framework que suporta esses requisitos. Ao utilizar comunicação assíncrona e interações orientadas a eventos, os sistemas podem lidar eficientemente com altos volumes de transações e manter o desempenho sob cargas instáveis. Essas características são particularmente apreciadas em ambientes onde as mudanças são muito espontâneas, como plataformas de e-commerce ou aplicações de IoT.
Alguns componentes-chave da EDA incluem:
-
Fontes de Eventos: São os produtores que geram eventos quando ações significativas ocorrem dentro do sistema. Exemplos incluem interações do usuário ou mudanças de dados.
-
Ouvintes: Estas são entidades que se inscrevem em eventos específicos e respondem quando esses eventos ocorrem. Os ouvintes permitem que o sistema reaja dinamicamente às mudanças.
-
Manipuladores: Estes são responsáveis por processar os eventos uma vez que são detectados pelos ouvintes, executando a lógica de negócios necessária ou fluxos de trabalho acionados pelo evento.
Neste artigo, você aprenderá como implementar o processamento de dados orientado a eventos usando Traefik, Kafka e Docker.
Aqui está um aplicativo simples hospedado no GitHub que você pode executar rapidamente para ter uma visão geral do que estará construindo hoje.
Sumário
Aqui está o que abordaremos:
Vamos começar!
Pré-requisitos
Antes de começar:
-
Implante uma instância do Ubuntu 24.04 com pelo menos 4 GB de RAM e um mínimo de 20 GB de espaço livre em disco para acomodar imagens do Docker, contêineres e dados do Kafka.
-
Acesse a instância com um usuário não root com privilégios de sudo.
-
Atualize o índice de pacotes.
sudo apt update
Compreendendo as Tecnologias
Apache Kafka
O Apache Kafka é uma plataforma distribuída de streaming de eventos construída para pipelines de dados de alto rendimento e aplicações de streaming em tempo real. Ele atua como a espinha dorsal para a implementação da EDA gerenciando eficientemente grandes volumes de eventos. O Kafka utiliza um modelo de publicação e inscrição, onde os produtores enviam eventos para tópicos, e os consumidores se inscrevem nesses tópicos para receber os eventos.
Algumas das principais características do Kafka incluem:
-
Alto Rendimento: Kafka é capaz de lidar com milhões de eventos por segundo com baixa latência, tornando-o adequado para aplicações de alto volume.
-
Tolerância a falhas: A arquitetura distribuída do Kafka garante a durabilidade e disponibilidade dos dados mesmo diante de falhas de servidor. Ele replica os dados em vários brokers dentro de um cluster.
-
Escalaridade: O Kafka pode facilmente escalar horizontalmente adicionando mais brokers ao cluster ou partições aos tópicos, atendendo às crescentes necessidades de dados sem reconfigurações significativas.
Traefik
Traefik é um moderno proxy reverso HTTP e balanceador de carga projetado especificamente para arquiteturas de microsserviços. Ele descobre automaticamente os serviços em execução em sua infraestrutura e direciona o tráfego adequadamente. O Traefik simplifica o gerenciamento de microsserviços, fornecendo capacidades de roteamento dinâmico com base em metadados de serviço.
Algumas das principais características do Traefik incluem:
-
Configuração Dinâmica: O Traefik atualiza automaticamente sua configuração de roteamento à medida que os serviços são adicionados ou removidos, eliminando a intervenção manual.
-
Balanceamento de Carga: Ele distribui eficientemente as solicitações recebidas entre várias instâncias de serviço, melhorando o desempenho e a confiabilidade.
-
Painel Integrado: O Traefik fornece um painel amigável para monitorar o tráfego e a saúde do serviço em tempo real.
Ao utilizar o Kafka e o Traefik em uma arquitetura orientada a eventos, você pode construir sistemas responsivos que lidam eficientemente com o processamento de dados em tempo real, mantendo alta disponibilidade e escalabilidade.
Como Configurar o Ambiente
Como Instalar o Docker no Ubuntu 24.04
- Instale os pacotes necessários.
sudo apt install ca-certificates curl gnupg lsb-release
- Adicione a chave GPG oficial do Docker.
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
- Adicione o repositório do Docker às suas fontes APT.
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
- Atualize novamente o índice de pacotes e instale o Docker Engine com o plugin Docker Compose.
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-compose-plugin
- Verifique para confirmar a instalação.
sudo docker run hello-world
Saída Esperada:
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
c1ec31eb5944: Pull complete
Digest: sha256:305243c734571da2d100c8c8b3c3167a098cab6049c9a5b066b6021a60fcb966
Status: Downloaded newer image for hello-world:latest
Hello from Docker!
This message shows that your installation appears to be working correctly.
Como Configurar o Docker Compose
O Docker Compose simplifica a gestão de aplicações multi-contêiner, permitindo que você defina e execute serviços em um único arquivo.
- Crie um diretório de projeto
mkdir ~/kafka-traefik-setup && cd ~/kafka-traefik-setup
- Crie um arquivo
docker-compose.yml
.
nano docker-compose.yml
- Adicione a seguinte configuração ao arquivo para definir seus serviços.
version: '3.8'
services:
kafka:
image: wurstmeister/kafka:latest
ports:
- "9092:9092"
environment:
KAFKA_ADVERTISED_LISTENERS: INSIDE://kafka:9092,OUTSIDE://localhost:9092
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INSIDE:PLAINTEXT,OUTSIDE:PLAINTEXT
KAFKA_LISTENERS: INSIDE://0.0.0.0:9092,OUTSIDE://0.0.0.0:9092
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
zookeeper:
image: wurstmeister/zookeeper:latest
ports:
- "2181:2181"
traefik:
image: traefik:v2.9
ports:
- "80:80" # Tráfego HTTP
- "8080:8080" # Painel do Traefik (inseguro)
command:
- "--api.insecure=true"
- "--providers.docker=true"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
Salve suas alterações com ctrl + o
, em seguida saia com ctrl + x
.
- Inicie seus serviços.
docker compose up -d
Saída Esperada:
[+] Running 4/4
✔ Network kafka-traefik-setup_default Created 0.2s
✔ Container kafka-traefik-setup-zookeeper-1 Started 1.9s
✔ Container kafka-traefik-setup-traefik-1 Started 1.9s
✔ Container kafka-traefik-setup-kafka-1 Started 1.9s
Como Construir o Sistema Orientado a Eventos
Como Criar Produtores de Eventos
Para produzir eventos no Kafka, você precisará implementar um produtor do Kafka. Abaixo está um exemplo usando Java.
- Crie um arquivo
kafka-producer.java
.
nano kafka-producer.java
- Adicione a seguinte configuração para um Produtor do Kafka.
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.clients.producer.RecordMetadata;
import java.util.Properties;
public class SimpleProducer {
public static void main(String[] args) {
// Configure as propriedades do produtor
Properties props = new Properties();
props.put("bootstrap.servers", "localhost:9092");
props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
// Crie o produtor
KafkaProducer<String, String> producer = new KafkaProducer<>(props);
try {
// Envie uma mensagem para o tópico "meu-topico"
ProducerRecord<String, String> record = new ProducerRecord<>("my-topic", "key1", "Hello, Kafka!");
RecordMetadata metadata = producer.send(record).get(); // Envio síncrono
System.out.printf("Sent message with key %s to partition %d with offset %d%n",
record.key(), metadata.partition(), metadata.offset());
} catch (Exception e) {
e.printStackTrace();
} finally {
// Feche o produtor
producer.close();
}
}
}
Salve suas alterações com ctrl + o
, em seguida saia com ctrl + x
.
Na configuração acima, o produtor envia uma mensagem com a chave “key1” e o valor “Olá, Kafka!” para o tópico “meu-topico”.
Como Configurar Tópicos do Kafka
Antes de produzir ou consumir mensagens, você precisa criar tópicos no Kafka.
- Use o script
kafka-topics.sh
incluído na sua instalação do Kafka para criar um tópico.
kafka-topics.sh --bootstrap-server localhost:9092 --create --topic <TopicName> --partitions <NumberOfPartitions> --replication-factor <ReplicationFactor>
Por exemplo, se você deseja criar um tópico chamado my-topic
com 3 partições e um fator de replicação de 1, execute:
docker exec <Kafka Container ID> /opt/kafka/bin/kafka-topics.sh --bootstrap-server localhost:9092 --create --topic my-topic --partitions 3 --replication-factor 1
Saída Esperada:
Created topic my-topic.
- Verifique para confirmar se o Tópico foi criado com sucesso.
docker exec -it kafka-traefik-setup-kafka-1 /opt/kafka/bin/kafka-topics.sh --bootstrap-server localhost:9092 --list
Saída Esperada:
my-topic
Como Criar Consumidores de Eventos
Após ter criado seus produtores e tópicos, você pode criar consumidores para ler mensagens desses tópicos.
- Crie um arquivo
kafka-consumer.java
.
nano kafka-consumer.java
- Adicione a seguinte configuração para um consumidor Kafka.
import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import java.time.Duration;
import java.util.Collections;
import java.util.Properties;
public class SimpleConsumer {
public static void main(String[] args) {
// Configure as propriedades do consumidor
Properties props = new Properties();
props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
props.put(ConsumerConfig.GROUP_ID_CONFIG, "my-group");
props.put(ConsumerConfig.KEY_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer");
props.put(ConsumerConfig.VALUE_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer");
// Crie o consumidor
KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props);
// Inscreva-se no tópico
consumer.subscribe(Collections.singletonList("my-topic"));
try {
while (true) {
// Consulte por novos registros
ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(100));
for (ConsumerRecord<String, String> record : records) {
System.out.printf("Consumed message with key %s and value %s from partition %d at offset %d%n",
record.key(), record.value(), record.partition(), record.offset());
}
}
} finally {
// Feche o consumidor
consumer.close();
}
}
}
Salve suas alterações com ctrl + o
, e depois saia com ctrl + x
.
Na configuração acima, o consumidor se inscreve em my-topic
e consulta continuamente por novas mensagens. Quando mensagens são recebidas, ele imprime suas chaves e valores juntamente com informações de partição e offset.
Como Integrar Traefik com o Kafka
Configure o Traefik como um Proxy Reverso.
Integrar o Traefik como um proxy reverso para o Kafka permite gerenciar o tráfego de entrada de forma eficiente, ao mesmo tempo em que proporciona recursos como roteamento dinâmico e terminação SSL.
- Atualize o arquivo
docker-compose.yml
.
version: '3.8'
services:
kafka:
image: wurstmeister/kafka:latest
ports:
- "9092:9092"
environment:
KAFKA_ADVERTISED_LISTENERS: INSIDE://kafka:9092,OUTSIDE://localhost:9092
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INSIDE:PLAINTEXT,OUTSIDE:PLAINTEXT
KAFKA_LISTENERS: INSIDE://0.0.0.0:9092,OUTSIDE://0.0.0.0:9092
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
labels:
- "traefik.enable=true"
- "traefik.http.routers.kafka.rule=Host(`kafka.example.com`)"
- "traefik.http.services.kafka.loadbalancer.server.port=9092"
zookeeper:
image: wurstmeister/zookeeper:latest
ports:
- "2181:2181"
traefik:
image: traefik:v2.9
ports:
- "80:80" # Tráfego HTTP
- "8080:8080" # Painel do Traefik (não seguro)
command:
- "--api.insecure=true"
- "--providers.docker=true"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
Nesta configuração, substitua kafka.example.com
pelo seu nome de domínio real. Os rótulos definem as regras de roteamento que o Traefik usará para direcionar o tráfego para o serviço Kafka.
- Reinicie seus serviços.
docker compose up -d
-
Acesse o painel do Traefik acessando
http://localhost:8080
no seu navegador web.Balanceamento de Carga com Traefik
O Traefik fornece recursos de balanceamento de carga integrados que podem ajudar a distribuir requisições entre várias instâncias dos seus produtores e consumidores de Kafka.
Estratégias para Balanceamento de Carga em Microserviços Orientados a Eventos
- Round Robin:
Por padrão, o Traefik utiliza uma estratégia round-robin para distribuir solicitações de entrada de forma equitativa entre todas as instâncias disponíveis de um serviço. Isso é eficaz para balancear a carga quando várias instâncias de produtores ou consumidores Kafka estão em execução.
- Sessões Sticky:
Se você precisar que as solicitações de um cliente específico sempre vão para a mesma instância (por exemplo, para manter o estado da sessão), você pode configurar sessões sticky no Traefik usando cookies ou cabeçalhos.
- Checks de Saúde:
Configure checks de saúde no Traefik para garantir que o tráfego seja roteado apenas para instâncias saudáveis de seus serviços Kafka. Você pode fazer isso adicionando parâmetros de verificação de saúde nas definições de serviço dentro do seu arquivo docker-compose.yml
:
labels:
- "traefik.http.services.kafka.loadbalancer.healthcheck.path=/health"
- "traefik.http.services.kafka.loadbalancer.healthcheck.interval=10s"
- "traefik.http.services.kafka.loadbalancer.healthcheck.timeout=3s"
Testando a Configuração
Verificando a Produção e Consumo de Eventos
- O Kafka fornece ferramentas de linha de comando integradas para teste. Inicie um produtor de Console.
docker exec -it kafka-traefik-setup-kafka-1 /opt/kafka/bin/kafka-console-producer.sh --broker-list localhost:9092 --topic my-topic
Após executar este comando, você pode digitar mensagens no terminal, que serão enviadas para o tópico Kafka especificado.
- Inicie outra sessão de terminal e comece um consumidor de console.
docker exec -it kafka-traefik-setup-kafka-1 /opt/kafka/bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic my-topic --from-beginning
Este comando exibirá todas as mensagens em my-topic
, incluindo aquelas produzidas antes do início do consumidor.
- Para ver como seus consumidores estão acompanhando os produtores, você pode executar o seguinte comando para verificar o atraso de um grupo específico de consumidores.
docker exec -it kafka-traefik-setup-kafka-1 /opt/kafka/bin/kafka-consumer-groups.sh --bootstrap-server localhost:9092 --describe --group <your-consumer-group>
Monitoramento e Registro
- Métricas Kafka:
O Kafka expõe inúmeras métricas que podem ser monitoradas usando JMX (Java Management Extensions). Você pode configurar o JMX para exportar essas métricas para sistemas de monitoramento como Prometheus ou Grafana. As principais métricas a serem monitoradas incluem:
-
Taxa de Mensagens: A taxa de mensagens produzidas e consumidas.
-
Atraso do Consumidor: A diferença entre o offset da última mensagem produzida e o offset da última mensagem consumida.
-
Saúde do Broker: Métricas relacionadas ao desempenho do broker, como taxas de solicitações e taxas de erro.
- Integração com Prometheus e Grafana:
Para visualizar as métricas do Kafka, você pode configurar o Prometheus para coletar métricas de seus brokers Kafka. Siga estes passos:
-
Habilite o Exportador JMX em seus brokers Kafka adicionando-o como um agente Java em sua configuração de broker.
-
Configure o Prometheus adicionando um trabalho de raspagem em seu arquivo de configuração (
prometheus.yml
) que aponta para o endpoint do seu Exportador JMX. -
Use o Grafana para criar painéis que visualizam essas métricas em tempo real.
Como Implementar Monitoramento para o Traefik
- Endpoint de Métricas do Traefik.
O Traefik fornece suporte integrado para exportar métricas via Prometheus. Para habilitar esse recurso, adicione a seguinte configuração em sua definição de serviço Traefik dentro do arquivo docker-compose.yml
:
command:
- "--metrics.prometheus=true"
- "--metrics.prometheus.addservice=true"
- Visualizando Métricas do Traefik com o Grafana.
Uma vez que o Prometheus está raspando as métricas do Traefik, você pode visualizá-las usando o Grafana:
-
Crie um novo painel no Grafana e adicione painéis que exibam métricas-chave do Traefik, como:
-
traefik_entrypoint_requests_total: Número total de solicitações recebidas.
-
traefik_backend_request_duration_seconds: Tempos de resposta dos serviços de backend.
-
traefik_service_requests_total: Total de solicitações encaminhadas para os serviços de backend.
- Configurando Alertas.
Configure alertas no Prometheus ou Grafana com base em limiares específicos (por exemplo, alta latência do consumidor ou aumento das taxas de erro).
Conclusão
Neste guia, você implementou com sucesso a Arquitetura Orientada a Eventos (EDA) utilizando Kafka e Traefik dentro do ambiente Ubuntu 24.04.
Recursos Adicionais
Para saber mais, você pode visitar:
Source:
https://www.freecodecamp.org/news/how-to-implement-event-driven-data-processing/