Alura > Cursos de Programação > Cursos de Java > Conteúdos de Java > Primeiras aulas do curso Mensageria com Java: RabbitMQ e Kafka

Mensageria com Java: RabbitMQ e Kafka

Fundamentos de Mensageria - Introducao

Apresentando o instrutor e o objetivo do curso

Olá! Meu nome é João Victor e serei o instrutor deste curso, que tem como objetivo mostrar como integrar uma aplicação Quarkus com recursos de mensageria, como o Kafka e o RabbitMQ.

Neste curso, trabalharemos com três aplicações, cada uma com perfis diferentes. Teremos uma aplicação para gerenciamento de auditoria de agências, cujos status são alterados pelo usuário. Também teremos um serviço responsável pelo cadastro de agências. Quando mencionamos agências, estamos nos referindo a agências bancárias simuladas nesses sistemas. Além disso, haverá um sistema de validação de agência, para verificar se o CNPJ deve estar ativo ou inativo.

Explicando o modelo reativo e a integração com RabbitMQ

Todas essas aplicações utilizarão o modelo reativo, permitindo que integremos recursos de mensageria nesse modelo, que é altamente valorizado no mercado de trabalho devido à sua escalabilidade e performance, características exigidas pelas aplicações corporativas atuais.

Neste curso, veremos a integração com o RabbitMQ, utilizando o MicroProfile para auxiliar nesse tipo de operação. Utilizaremos anotações para manter o código sempre limpo, e toda a parte de configuração estará no nosso Application Properties.

Detalhando o sistema de auditoria e validação

No sistema de auditoria, mostraremos como receber mensagens do RabbitMQ.

Vamos configurar, por exemplo, no Validation, que quando houver uma troca de status da agência, enviaremos uma auditoria. Também teremos toda a parte do MicroProfile para o ReptMQ, com o Outing On, ou seja, enviando uma mensagem como producer de ReptMQ.

Integrando Kafka e gerenciamento de contratos

Além disso, no nosso Banking Validation, além do ReptMQ, trabalharemos com o Kafka. Não apenas com o Kafka, mas também conseguiremos trabalhar com o gerenciamento de contratos com o EIVRO, para garantir que, quando temos dois serviços, um producer e um consumer, eles possuam contratos fortes para evitar quebras silenciosas. Para isso, utilizaremos o Schema Registry.

Implementando o padrão Saga no Banking Service

No Banking Service, que é nosso sistema de adição de agências bancárias, haverá uma ligação muito forte com o Banking Validation. Assim, toda vez que inativarmos uma agência no Banking Validation, enviaremos uma mensagem Kafka para o Banking Service, e será imprescindível que ela exclua essa agência do banco de dados. Para garantir isso no mundo de microserviços, onde não há uma transação ACID no banco, utilizaremos o Saga Pattern (padrão Saga) para gerenciar essas transações no modelo distribuído.

Concluindo a introdução do curso

Este é um curso bastante rico, com muitos detalhes, que é utilizado no mercado de trabalho atualmente. Temos certeza de que, se continuarmos juntos, será uma experiência muito proveitosa. Vamos seguir para o próximo vídeo e continuar nossa jornada. Nos vemos lá, muito obrigado!

Fundamentos de Mensageria - Por que usar mensageria

Discutindo o uso de mensageria

Quando discutimos o uso de mensageria, é fundamental compreender por que devemos utilizá-la. Como pessoas desenvolvedoras atuantes no mercado de trabalho, precisamos tomar decisões baseadas na necessidade e no negócio, em vez de seguir tendências. Muitas vezes, ouvimos sobre o uso de mensageria, mas é importante refletir se realmente faz sentido em determinado cenário. A análise deve sempre ser motivada pelo porquê e onde utilizar.

Vamos começar discutindo as razões para usar mensageria e, consequentemente, entender em quais cenários esse recurso se encaixa melhor. Primeiramente, é necessário compreender que toda integração entre recursos, seja entre sistemas, um sistema e um banco de dados, ou qualquer outro tipo de comunicação, apresenta desafios. Por exemplo, quando falamos em integração de sistemas, geralmente pensamos na base REST. A base REST é um endpoint onde chamamos a aplicação com um método HTTP, o que gera algum retorno ou permite a passagem de informações para serem adicionadas a outro sistema. Essa integração direta e síncrona é comum, mas gera uma dependência entre os sistemas.

Explorando limitações da integração síncrona

Por exemplo, se o sistema B, que recebe uma requisição, sofre alta latência ou está fora do ar, ocorre uma falha em cascata. Se o sistema A chama o sistema B e ele está fora, o sistema A falha. Embora existam recursos de resiliência que minimizam o impacto para o cliente, o acoplamento entre sistemas é real. Quando uma falha ocorre em um sistema, ela impacta diretamente o outro. A integração síncrona, relacionada à base REST, é uma comunicação em tempo real, onde o produtor, como o sistema A, espera uma resposta imediata. O exemplo clássico é a base REST.

Um dos trade-offs dessa relação entre microserviços é o forte acoplamento gerado pela base REST. Não estamos dizendo que não se deve utilizá-la, mas é importante entender em quais cenários a mensageria se encaixa. Não existe uma solução única; há cenários para mensageria e muitos para a base REST. As limitações desse modelo incluem o bloqueio no modelo tradicional. Embora existam modelos reativos que não têm esse bloqueio de tempo de espera, ainda precisamos de uma thread disponível para receber a resposta do sistema de destino. No modelo tradicional, a thread fica bloqueada até a resposta. No reativo, ela não fica bloqueada, mas ainda precisamos de uma thread para buscar a informação quando o sistema de destino responde.

Abordando limitações de escala e impacto de erros

Há uma limitação em termos de escala. Os recursos dependem uns dos outros, e não podemos escalar o serviço A sem considerar se o recurso B está preparado para a quantidade de requisições. Se o sistema B não escala junto, o aumento de requisições pode impactar o banco de dados e causar problemas. Além disso, há o impacto em caso de erros. Se o sistema B falha, ele impacta diretamente o A, mesmo com formas de mitigação.

Agora, vamos falar sobre o modelo assíncrono, que envolve mensageria. No modelo assíncrono, enviamos mensagens. O produtor, ou sistema A, envia uma mensagem, e espera-se que o sistema de destino, o microserviço B, receba essa mensagem. A principal diferença é o envio de mensagens em vez de chamadas diretas.

Introdução à mensageria em microserviços

As requisições em sistemas de microserviços acabam ficando desacopladas. Vamos considerar um cenário com um microserviço A, um microserviço B e um recurso de mensageria. Quando enviamos uma mensagem do microserviço A para a mensageria, a partir desse momento, o microserviço A já não tem mais uma obrigação direta com o serviço B. O consumidor, então, se encarrega de consumir a mensagem, promovendo o desacoplamento temporal entre os serviços.

O elemento central entre os serviços são filas ou tópicos. Ao longo do curso, entenderemos a diferença entre eles, quando utilizar um ou outro, e as especificidades de cada um. Inicialmente, estamos introduzindo o conceito de mensageria e seus benefícios. Embora não seja uma solução universal, a mensageria oferece vantagens como o desacoplamento entre serviços, o que reduz a necessidade de recursos de resiliência que seriam necessários em sistemas baseados em APIs REST.

Explorando o modelo assíncrono e seus benefícios

No modelo assíncrono, enviamos a mensagem para o recurso de mensageria. Se o sistema B estiver fora do ar, ele poderá consumir as mensagens quando voltar a funcionar, sem impactar o sistema A. Isso resulta em maior resiliência a falhas, desde que o sistema de mensageria esteja operacional. Além disso, a mensageria permite escalabilidade horizontal, reduzindo a preocupação com recursos, e oferece tolerância a picos de carga.

Com um consumidor, conseguimos implementar o conceito de backpressure (pressão reversa), onde o consumidor dita o ritmo de consumo das mensagens. Diferente de um sistema REST, onde o aumento de carga no sistema A pode impactar o sistema B, na mensageria, o consumidor solicita as mensagens no ritmo que consegue processar, mantendo o sistema saudável.

Casos de uso para mensageria

A mensageria é útil em diversos cenários, como processamento de pedidos em e-commerce, onde as operações são desacopladas e não requerem resposta imediata. Exemplos incluem o envio de mensagens para atualizar o estoque após uma compra. Outros casos de uso incluem sistemas antifraude, notificações, integrações entre domínios de negócio, filas de e-mails e logs de auditoria. A mensageria pode ser aplicada em inúmeros cenários, e ao longo do curso, aprenderemos a identificar quando faz sentido utilizá-la em nossos sistemas.

Conclusão

Para sistemas resilientes, a mensageria é amplamente utilizada. Dois sistemas não dependem diretamente um do outro, e as mensagens são armazenadas até que possam ser consumidas, mesmo em caso de falha de um dos microserviços. Isso permite desacoplar, proteger e escalar nossos sistemas, com controle mais fino de escala e desacoplamento, que são fundamentais para arquiteturas distribuídas saudáveis.

É importante ressaltar que a mensageria não substitui o modelo REST, mas oferece uma alternativa valiosa no contexto de microserviços. Ao longo do tempo, entenderemos melhor quando e como utilizar mensageria. Esta introdução visa apresentar os conceitos iniciais, e nos próximos vídeos, exploraremos mais recursos de mensageria e os diferentes tipos disponíveis. Nos encontramos no próximo vídeo. Até lá!

Fundamentos de Mensageria - Conceitos essenciais

Discutindo a importância da mensageria

No primeiro vídeo, discutimos a importância do uso da mensageria. Entendemos em quais cenários podemos substituir uma API REST pela mensageria ou utilizá-la em um sistema que já possui API REST, especialmente quando precisamos de desacoplamento. Agora, vamos explorar alguns conceitos fundamentais.

A mensageria não se limita a um único tipo. Trata-se de sistemas que enviam e recebem mensagens, funcionando como um sistema central que facilita esse processo entre serviços. Existem diferentes tipos de mensageria, como filas e tópicos, e é importante compreendermos esses conceitos antes de aplicá-los na prática. Assim, quando revisitarmos esses conceitos em aulas práticas, eles farão mais sentido.

Explicando conceitos fundamentais de mensageria

Um conceito importante é o de broker (intermediário). Em sistemas como RabbitMQ e Kafka, o broker é o serviço central de mensageria. Ele gerencia filas, tópicos e roteamento, e é essencial para a comunicação entre microserviços. Exemplos de brokers incluem RabbitMQ e Kafka, mas o conceito se aplica a qualquer sistema de mensageria, como SQS e SNS.

Outro conceito é o de fila, ou queue. Essa estrutura segue o modelo FIFO (First In, First Out), onde o primeiro dado a entrar é o primeiro a sair. Isso é ideal para tarefas independentes, onde um serviço A envia uma mensagem que será consumida por um serviço B. Cada mensagem é processada por um único consumidor, o que é um cenário ideal para o uso de filas.

Explorando o funcionamento do RabbitMQ

No RabbitMQ, temos o Exchange e o roteamento. O Exchange recebe mensagens dos produtores e decide para qual fila a mensagem será enviada. Um broker pode ter várias filas, e cada fila pode ser consumida por diferentes consumidores. Existem diferentes tipos de Exchange, como Direct, Topic, Fanout e Headers.

Comparando RabbitMQ e Kafka

O Kafka possui algumas diferenças. No Kafka, o tópico é a unidade lógica onde as mensagens são publicadas. Diferentemente das filas, os tópicos permitem que as mensagens sejam enviadas para múltiplos consumidores. Vamos explorar essas diferenças à medida que avançamos no curso, começando com o RabbitMQ e, posteriormente, abordando o Kafka.

Quando utilizamos um Direct, por exemplo, enviamos uma mensagem para uma fila, e o único consumidor irá consumi-la. No caso de um tópico Kafka, podemos ter uma ou múltiplas partições, e essas partições são onde as mensagens são enviadas. Em cada partição, pode haver um consumidor de um serviço. Isso implica que não conseguimos garantir a ordem que temos no FIFO. Portanto, quando nosso produto envia várias mensagens, elas são distribuídas nas partições, e vários consumidores as consomem, mas não conseguimos garantir essa ordem.

Entendendo o conceito de stream no Kafka

O Kafka, então, começa a mudar do conceito de FIFO para um stream de dados. É importante entender esse termo, pois será bastante discutido. Os consumidores operam de forma independente, sem ordem, pois podemos ter um consumidor para cada partição, ou diferentes consumidores para cada partição. Vamos entender como isso funciona no Kafka em relação ao RabbitMQ.

Os termos de publicador, produtor e consumidor são importantes. O publicador é o serviço que publica mensagens no broker, enquanto o consumidor é o serviço que lê e processa mensagens. Trata-se de comunicação assíncrona indireta. Embora falemos de serviços, não é necessário que sejam microserviços. Quando configuramos nosso Kafka local, por exemplo, podemos publicar uma mensagem no Kafka e consumi-la no CLI do Kafka. Não é necessário um sistema específico para consumir, mas, geralmente, em microserviços, temos um sistema como produtor e outro como consumidor.

Explorando garantias de entrega e persistência

Existem garantias de entrega que podemos configurar. O At Most Once pode perder mensagens, mas nunca as duplica. O At Least Once garante a entrega, mas pode duplicar. O Exactly Once oferece entrega única e confiável, exigindo um sistema confiável de recebimento de mensagens. A durabilidade e persistência variam entre Kafka e RabbitMQ, mas, basicamente, as mensagens podem ser mantidas em memória ou disco, dependendo da arquitetura e dos recursos de mensageria. A persistência garante recuperação após falha, e a configuração depende da prioridade e custo. Devemos considerar se queremos manter as mensagens em um banco de dados ou não. Após o consumo, pode não ser necessário garantir que a mensagem esteja salva.

Resumindo filas versus streams

Vamos resumir como funcionam filas versus streams. O Kafka é entendido como uma grande escala de dados passando pelas partições, permitindo escalabilidade. A fila segue o padrão FIFO, sendo mais ordenada. Na mensageria, precisamos analisar qual se adequa melhor aos nossos sistemas. Comparando fila e stream, no Kafka, uma mensagem pode ser reprocessada várias vezes por diferentes consumidores, enquanto na fila é um para um. A ordem na fila é garantida, mas no Kafka, por partição, não conseguimos garantir a ordem. Existem formas de garantir, mas, nativamente, o Kafka não foi feito para isso. A mensagem na fila é removida após o consumo, enquanto no Kafka podemos configurar o tempo de retenção. O Kafka registra um log da mensagem, que fica salvo por um tempo determinado. Podemos configurar o tempo de retenção e, se necessário, voltar um offset para consumir as mensagens novamente.

Concluindo o uso de filas e streams

O uso comum da fila é para tarefas independentes, enquanto no Kafka é para streams de dados e integrações de dados. Ao longo do curso, identificaremos outros conceitos e diferenças entre os sistemas, mas isso já serve como base. No próximo vídeo, continuaremos explorando o recurso de mensageria e, eventualmente, integraremos nossos sistemas com RabbitMQ e Kafka. Até lá!

Sobre o curso Mensageria com Java: RabbitMQ e Kafka

O curso Mensageria com Java: RabbitMQ e Kafka possui 285 minutos de vídeos, em um total de 49 atividades. Gostou? Conheça nossos outros cursos de Java em Programação, ou leia nossos artigos de Programação.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda Java acessando integralmente esse e outros cursos, comece hoje!

Conheça os Planos para Empresas