top of page
pedrobusko

Quando usar request-response com o Apache Kafka?

Este é um artigo traduzido originalmente publicado dia 03/6/2022 no blog do Kai Waehner: "When to use Request-Response with Apache Kafka?". Assine a newsletter do Kai para se manter atualizado com novas publicações.


Como posso fazer comunicação request-response com o Apache Kafka? Essa é uma das perguntas mais comuns que recebo regularmente. Esta postagem de blog explora quando (não) usar esse padrão de troca de mensagens, as diferenças entre comunicação síncrona e assíncrona, os prós e contras em comparação com CQRS e origem de eventos e como implementar solicitação-resposta na infraestrutura de streaming de dados.


 

Como posso fazer comunicação de solicitação-resposta com o Apache Kafka? Essa é uma das perguntas mais comuns que recebo regularmente. Esta postagem de blog explora quando (não) usar esse padrão de troca de mensagens , as diferenças entre comunicação síncrona e assíncrona, os prós e contras em comparação com CQRS e origem de eventos e como implementar solicitação-resposta na infraestrutura de streaming de dados.


Source: Kai Waehner - When to use Request-Response with Apache Kafka?


Padrões de fila de mensagens em streaming de dados com Apache Kafka

Antes de entrar neste post, quero que você saiba que este conteúdo faz parte de uma série de blogs sobre “JMS, Message Queues e Apache Kafka” :

Vou linkar os outros posts aqui assim que estiverem disponíveis. Por favor , siga minha newsletter para se atualizar em tempo real sobre novos posts . (sem spam ou anúncios)


O que é o padrão de troca de mensagens de request-response?


Request-response é um dos principais métodos que os computadores usam para se comunicarem em uma rede .

O primeiro aplicativo envia uma solicitação de alguns dados. O segundo aplicativo responde à solicitação . É um padrão de troca de mensagens no qual um solicitante envia uma mensagem de solicitação a um sistema replicador, que recebe e processa a solicitação, retornando uma mensagem em resposta.

O request-response é ineficiente e pode sofrer muita latência dependendo do caso de uso . HTTP ou melhor gRPC é adequado para alguns casos de uso. A solicitação-resposta é “substituída” pelo padrão CQRS ( Segregação de responsabilidade de comando e consulta) com Kafka para streaming de dados . O CQRS não é possível com a API JMS, pois o JMS não fornece recursos de estado e não possui recursos de origem de eventos. Vamos aprofundar essas declarações.


Request-response (HTTP) x transmissão de dados (Kafka)


Antes de discutir a comunicação síncrona e assíncrona, vamos explorar os conceitos por trás de solicitação-resposta e streaming de dados. Tradicionalmente, estes são dois paradigmas diferentes:

Request-response (HTTP):

  • Normalmente síncrono

  • Ponto a ponto

  • Alta latência (em comparação com streaming de dados)

  • API predefinida

Transmissão de dados (Kafka):

  • Processamento contínuo

  • Muitas vezes assíncrono

  • Orientado a eventos

  • Baixa latência

  • Eventos de uso geral

A maioria das arquiteturas precisa de request-response para comunicação ponto a ponto (por exemplo, entre um servidor e um aplicativo móvel) e fluxo de dados para processamento contínuo de dados . Com isso em mente, vejamos os casos de uso em que o HTTP é usado com o Kafka.


Comunicação Síncrona vs. Assíncrona


O padrão de troca de mensagens de request-response geralmente é implementado de forma puramente síncrona . No entanto, o request-response também pode ser implementada de forma assíncrona , com uma resposta sendo retornada em algum momento posterior desconhecido.

Vejamos os exemplos mais comuns de trocas de mensagens: REST, filas de mensagens e fluxo de dados.


APIs Restful Síncronas (HTTP)


Um serviço da Web é a principal tecnologia por trás da comunicação síncrona no desenvolvimento de aplicativos e na integração de aplicativos corporativos. Enquanto WSDL e SOAP eram dominantes há muitos anos, REST/HTTP é o padrão de comunicação em quase todos os serviços da web hoje .

Não vou entrar no debate “HTTP vs. REST” neste post. Em resumo, REST (transferência de estado representacional) tem sido empregado em toda a indústria de software e é um conjunto de diretrizes amplamente aceito para a criação de APIs da Web confiáveis ​​e sem estado. Uma API web que obedece às restrições REST é informalmente descrita como RESTful. As APIs da Web RESTful geralmente são baseadas em métodos HTTP.

As chamadas de serviço da Web síncronas por HTTP mantêm uma conexão aberta e aguardam até que a resposta seja entregue ou o período de tempo limite expire.

A latência dos serviços da Web HTTP é relativamente alta . Requer a configuração e desmontagem de uma conexão TCP para cada iteração de solicitação-resposta ao usar HTTP. Para ser claro: a latência ainda é boa o suficiente para muitos casos de uso.

Outra possível desvantagem é que as solicitações HTTP podem bloquear a espera pelo processamento da solicitação principal da fila e podem exigir a configuração de disjuntores HTTP no servidor se houver muitas solicitações HTTP pendentes.


Fila de mensagens assíncronas (IBM MQ, RabbitMQ)


O paradigma de fila de mensagens é um irmão do padrão de design publicador/assinante e normalmente é uma parte de um sistema de middleware orientado a mensagens mais extenso. A maioria dos sistemas de mensagens suporta os modelos de editor/assinante e fila de mensagens em sua API, por exemplo, Java Message Service (JMS). Leia o artigo “JMS Message Queue vs. Apache Kafka”(post original: Comparison: JMS Message Queue vs. Apache Kafka) se você é novo nesta discussão.

Produtores e consumidores são dissociados uns dos outros e se comunicam de forma assíncrona. A fila de mensagens armazena eventos até que sejam consumidos com sucesso.

A maioria dos produtos de middleware de fila de mensagens fornece APIs de solicitação-resposta integradas . Sua comunicação é assíncrona . A implementação usa IDs de correlação.

A API de request-response (por exemplo, em JMS) cria uma fila ou tópico temporário que é referenciado na solicitação a ser usada pelo consumidor, obtendo o terminal de resposta da solicitação. O ID é usado para separar as solicitações do solicitante único. Essas filas ou tópicos também estão disponíveis apenas enquanto o solicitante estiver ativo com uma sessão para a resposta.

Tal implementação com uma fila ou tópico temporário não faz sentido no Kafka . Eu realmente vi empresas tentando fazer isso. Kafka não funciona assim. A consequência foi muitas partições e tópicos no cluster Kafka. Problemas de escalabilidade e desempenho foram a consequência.


Streaming de dados assíncrono (Apache Kafka)


O streaming de dados processa continuamente os eventos ingeridos de fontes de dados. Esses dados devem ser processados ​​de forma incremental usando técnicas de processamento de fluxo sem ter acesso a todos os dados.

O paradigma de comunicação assíncrona é como as filas de mensagens. Ao contrário das filas de mensagens, o streaming de dados fornece armazenamento de eventos de longo prazo e capacidade de reprodução de informações históricas . A consequência é uma verdadeira dissociação entre produtores e consumidores. Na maioria das implantações do Apache Kafka, vários produtores e consumidores com paradigmas de comunicação e recursos de latência muito diferentes enviam e lêem eventos.

O Apache Kafka não fornece APIs de solicitação-resposta integradas. Isso não é necessariamente uma coisa ruim, como algumas pessoas pensam. O streaming de dados fornece diferentes padrões de design. Essa é a principal razão para esta postagem no blog! Vamos explorar as compensações do padrão de solicitação-resposta em sistemas de mensagens e entender abordagens alternativas que se adequam melhor a um mundo de streaming de dados. Mas este post também explora como implementar solicitação-resposta assíncrona ou síncrona com Kafka .

Mas lembre-se: não reutilize seu “conhecimento legado” sobre HTTP e MQ e tente reconstruir os mesmos padrões com o Apache Kafka . Dito isto, a solicitação-resposta também é possível com Kafka. Mais sobre isso nas seções a seguir.


Request-response versus CQRS e Event Sourcing


CQRS (Command Query Responsibility Segregation) afirma que cada método deve ser um comando que executa uma ação ou uma consulta que retorna dados para o chamador, mas não ambos. Os serviços tornam-se verdadeiramente desacoplados uns dos outros.

Martin Fowler tem um bom diagrama para CQRS :


Source: Kai Waehner - When to use Request-Response with Apache Kafka?


A origem de eventos é um padrão de arquitetura em que as entidades não rastreiam seu estado interno usando serialização direta ou mapeamento relacional de objeto, mas lendo e confirmando eventos em um armazenamento de eventos .

Quando a origem de eventos é combinada com CQRS e design orientado a domínio , as raízes agregadas são responsáveis ​​por validar e aplicar comandos (geralmente fazendo com que seus métodos de instância sejam invocados de um manipulador de comandos) e, em seguida, publicar eventos.

Com o CQRS, o estado é atualizado em relação a cada mensagem de evento relevante. Portanto, o estado é sempre conhecido . Consultar o estado armazenado na visualização materializada (por exemplo, uma KTable no Kafka Streams) é eficiente. Com solicitação-resposta, o servidor deve calcular ou determinar o estado de cada solicitação. Com o CQRS, ele é calculado/atualizado apenas uma vez, independentemente do número de consultas de estado no momento em que o relevante ocorre.

Esses princípios se encaixam perfeitamente no mundo do streaming de dados . O Apache Kafka é um armazenamento distribuído que anexa eventos de entrada ao log de confirmação imutável. O verdadeiro desacoplamento e a capacidade de reprodução de eventos são integrados à infraestrutura Kafka pronta para uso. A maioria das arquiteturas de microsserviços modernas com design orientado a domínio são construídas com Apache Kafka, não REST ou MQ .


Não use Request-Response no Kafka se não for necessário!


Se você criar uma arquitetura empresarial moderna e novos aplicativos, aplique os padrões de design naturais que funcionam melhor com a tecnologia . Lembre-se: o streaming de dados é uma tecnologia diferente dos serviços da Web e das filas de mensagens! CQRS com fonte de eventos é o melhor padrão para a maioria dos casos de uso no mundo Kafka:


Source: Kai Waehner - When to use Request-Response with Apache Kafka?


Não use o conceito de solicitação-resposta com o Kafka se não for realmente necessário! Kafka foi construído para streaming de dados e verdadeira dissociação entre vários produtores e consumidores.

Isso é verdade mesmo para cargas de trabalho transacionais. Uma transação NÃO precisa de comunicação síncrona . A API Kafka suporta transações de missão crítica (embora seja assíncrona e distribuída por natureza). Pense em fazer um pagamento bancário . Nunca é síncrono, mas um processo de negócios complexo com muitos eventos independentes dentro e entre organizações .


Request-response síncrona vs. assíncrona com Apache Kafka

Depois que expliquei que a solicitação-resposta não deve ser a primeira ideia ao criar um novo aplicativo Kafka, isso não significa que não seja possível. E, às vezes, é a abordagem melhor, mais simples ou mais rápida para resolver um problema. Portanto, vejamos exemplos de implementações de solicitação-resposta síncronas e assíncronas com Kafka . O padrão de solicitação-resposta pode ser implementado com Kafka. Mas de forma diferente. Tentar fazer isso como em um agente de mensagens JMS (com filas temporárias etc.) acabará matando o cluster Kafka (porque funciona de maneira diferente). No entanto, os conceitos usados ​​são os mesmos que na API JMS, como um ID de correlação.

Request-response assíncrona com Apache Kafka

O projeto Spring e suas bibliotecas Kafka Spring Boot Kafka Template têm um ótimo exemplo do padrão de solicitação-resposta assíncrono criado com Kafka . Confira " org.springframework.kafka.requestreply.ReplyingKafkaTemplate ". Ele cria aplicativos de solicitação/resposta usando a API Kafka facilmente. O exemplo é interessante, pois implementa o request/reply assíncrono , que é mais complicado de escrever se você estiver usando, por exemplo, a API JMS).


O que é ótimo no Spring é a disponibilidade de modelos e assinaturas de métodos fáceis de usar . A estrutura permite o uso de padrões de design sem código personalizado para implementá-los. Por exemplo, aqui estão os dois métodos Java para request-response com Kafka:


RequestReplyFuture<K, V, R> sendAndReceive (ProducerRecord<K, V> registro) ;


RequestReplyFuture<K, V, R> sendAndReceive (ProducerRecord<K, V> registro, Duration replyTimeout) ;


O resultado é um ListenableFuture que é preenchido de forma assíncrona com o resultado (ou uma exceção, para um tempo limite). O resultado também tem uma sendFuture propriedade, que é o resultado de chamar KafkaTemplate.send(). Você pode usar esse futuro para determinar o resultado da operação de envio.


Solicitação-resposta síncrona com Apache Kafka

Outro excelente artigo do DZone fala sobre request/response síncrona usando modelos Spring Kafka . O exemplo mostra um serviço Kafka para calcular a soma de dois números com comportamento síncrono de solicitação-resposta para retornar o resultado :

Source: Kai Waehner - When to use Request-Response with Apache Kafka?


O Spring define automaticamente um ID de correlação no registro do produtor . Esse ID de correlação é retornado como está pela @SendToanotação na extremidade do consumidor.

A documentação do Spring para Kafka Templates tem muitos detalhes e exemplos de código sobre o padrão Request/Reply para Kafka. Usando Spring, o padrão de solicitação/resposta é bastante simples de implementar com o Kafka. Se você não estiver usando o Spring, poderá aprender como fazer solicitação-resposta com o Kafka em seu framework. Essa é a beleza do código aberto…


Combinação de Data Streaming e API REST

Os exemplos acima mostraram como você pode implementar o padrão de solicitação-resposta com o Apache Kafka . No entanto, ainda é apenas a segunda melhor abordagem e geralmente é um antipadrão para dados de streaming .


Streaming de dados e APIs REST de solicitação-resposta geralmente são combinados para obter o melhor dos dois mundos . Escrevi uma postagem de blog dedicada sobre “ Casos de uso e arquiteturas para APIs HTTP e REST com Apache Kafka ”.


Apache Kafka e gerenciamento de API


Uma abordagem muito comum é implementar aplicativos em tempo real em escala com o ecossistema Kafka, mas depois colocar uma camada de gerenciamento de API no topo para expor os eventos como API para o mundo externo (outro domínio de negócios interno ou um aplicativo de terceiros B2B ).

Não importa como você obtém dados no hub de dados de streaming, no lado direito, a API REST do Kafka é usada para expor eventos via HTTP . Uma solução de gerenciamento de API lida com os requisitos de segurança e monetização/faturamento na interface Kafka:


Source: Kai Waehner - When to use Request-Response with Apache Kafka?


Leia mais sobre essa discussão na postagem do blog “Apache Kafka e API Management / API Gateway – Amigos, Inimigos ou Um pouco dos dois?“(post original: Apache Kafka and API Management / API Gateway – Friends, Enemies or Frenemies?). Abrange a relação entre Apache Kafka e plataformas de gerenciamento de API como Kong, MuleSoft Anypoint ou Apigee do Google.


Stream Exchange para compartilhamento de dados internos e externos com o Apache Kafka

Depois de discutir a relação entre APIs, comunicação request-response e Kafka, vamos explorar uma tendência significativa no mercado: Data Mesh (a palavra da moda) e troca de fluxo para compartilhamento de dados em tempo real (o solucionador de problemas) . O Data Mesh é um novo paradigma de arquitetura que recebe muita atenção nos dias de hoje. Nenhuma tecnologia é perfeita para construir uma malha de dados . Uma plataforma em tempo real descentralizada e escalável, como o Apache Kafka, geralmente é o coração da infraestrutura Data Mesh, complementada por muitas outras plataformas de dados para resolver problemas de negócios. O compartilhamento de dados nativos de fluxo em vez de usar APIs de request-response e REST no meio é a evolução natural para muitos casos de uso:

Source: Kai Waehner - When to use Request-Response with Apache Kafka?

Use streaming de dados e solicitação-resposta juntos!

A maioria das arquiteturas precisa de request-response para comunicação ponto a ponto (por exemplo, entre um servidor e um aplicativo móvel) e fluxo de dados para processamento contínuo de dados . A comunicação de request-response síncrona e assíncrona pode ser implementada com o Apache Kafka . No entanto, o CQRS e o Event Sourcing são a abordagem melhor e mais natural para streaming de dados na maioria das vezes . Entenda as diferentes opções e suas compensações e use a ferramenta certa (neste caso, o padrão de projeto correto) para o trabalho.

Qual é a sua estratégia para usar request-response com streaming de dados? Como você implementa a comunicação em seus aplicativos Apache Kafka? Conecte comigo e com o Kai no LinkedIn e vamos discutir isso! Mantenha-se informado sobre as novas postagens do blog assinando a newsletter.

123 visualizações0 comentário

Comments


bottom of page