<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Wallace Maia</title>
    <description>The latest articles on DEV Community by Wallace Maia (@wallace_maia).</description>
    <link>https://dev.to/wallace_maia</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4150546%2Fd6653ec4-4dd8-4e77-b58a-6d71247a959f.jpg</url>
      <title>DEV Community: Wallace Maia</title>
      <link>https://dev.to/wallace_maia</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/wallace_maia"/>
    <language>en</language>
    <item>
      <title>Comunicação de microserviços em arquiteturas Spring Boot: Chamadas síncronas, Eventos e Integração de Inteligência Artificial com Spring AI</title>
      <dc:creator>Wallace Maia</dc:creator>
      <pubDate>Wed, 30 Sep 2026 02:20:32 +0000</pubDate>
      <link>https://dev.to/wallace_maia/comunicacao-de-microservicos-em-arquiteturas-spring-boot-chamadas-sincronas-eventos-e-integracao-53ck</link>
      <guid>https://dev.to/wallace_maia/comunicacao-de-microservicos-em-arquiteturas-spring-boot-chamadas-sincronas-eventos-e-integracao-53ck</guid>
      <description>&lt;p&gt;&lt;strong&gt;Resumo&lt;/strong&gt; &lt;br&gt;
Este artigo analisa estratégias de comunicação entre serviços Spring Boot, discutindo critérios para a escolha entre chamadas síncronas e mecanismos orientados a eventos. Abordam-se ainda formas de integrar serviços de inteligência artificial (IA) sem acoplá-los ao restante da aplicação. São examinados Spring Cloud OpenFeign, Service Discovery, Spring Cloud LoadBalancer, webhooks, mensageria e mecanismos de resiliência, com exemplos derivados de uma aplicação SaaS em desenvolvimento.&lt;/p&gt;


&lt;h3&gt;
  
  
  1. Introdução
&lt;/h3&gt;

&lt;p&gt;À medida que uma aplicação cresce e suas responsabilidades são separadas, torna-se necessário definir como os serviços se comunicarão. A criação de projetos Spring Boot independentes é relativamente simples. A dificuldade surge quando um serviço depende de dados ou regras pertencentes a outro, por exemplo ao consultar informações de usuários, executar uma regra de negócio ou acessar uma API externa. Surge também a necessidade de processar tarefas demoradas sem manter uma requisição HTTP aberta durante todo o processamento.&lt;/p&gt;

&lt;p&gt;Nesse contexto, a comunicação entre serviços deixa de ser um detalhe de implementação e passa a ser uma decisão arquitetural. Este trabalho discute o tema com ênfase em &lt;strong&gt;Spring Cloud OpenFeign&lt;/strong&gt;, &lt;strong&gt;Service Discovery&lt;/strong&gt;, &lt;strong&gt;Spring Cloud LoadBalancer&lt;/strong&gt;, chamadas HTTP síncronas, &lt;strong&gt;webhooks&lt;/strong&gt;, eventos e processamento assíncrono. Apresenta-se também sua aplicação em um SaaS real, no qual uma camada de IA é isolada do backend principal.&lt;/p&gt;
&lt;h3&gt;
  
  
  2. O desafio da localização de serviços
&lt;/h3&gt;

&lt;p&gt;Uma arquitetura monolítica pode ser representada de forma simples. Com a separação de responsabilidades, a API principal passa a depender de múltiplos serviços, como autenticação, IA, pagamentos e notificações. Surge então a questão central: como a API principal localiza e invoca esses serviços?&lt;/p&gt;

&lt;p&gt;A alternativa mais simples é registrar endereços fixos no código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nl"&gt;http:&lt;/span&gt;&lt;span class="c1"&gt;//localhost:8082&lt;/span&gt;
&lt;span class="nl"&gt;http:&lt;/span&gt;&lt;span class="c1"&gt;//10.0.4.27:8082&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Essa abordagem funciona até que ocorra alguma mudança de infraestrutura, como a alteração da instância, a execução de múltiplas réplicas, a migração de ambiente ou a adoção de Docker ou Kubernetes. Nesses casos, o endereço físico embutido no código torna-se uma fonte de acoplamento e de manutenção onerosa. O &lt;strong&gt;Service Discovery&lt;/strong&gt; foi concebido para solucionar esse problema.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Service Discovery
&lt;/h3&gt;

&lt;p&gt;No Service Discovery, o consumidor deixa de perguntar "onde está o serviço?" e passa a indicar "qual serviço é necessário?". No Spring Cloud, isso se expressa da seguinte forma:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@FeignClient&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"ai-service"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O código torna-se independente do endereço concreto da instância (&lt;code&gt;localhost:8082&lt;/code&gt;, &lt;code&gt;10.0.2.15:8082&lt;/code&gt; ou &lt;code&gt;ai-service:8082&lt;/code&gt;), que é resolvido pela infraestrutura de descoberta. Um exemplo clássico no ecossistema Spring é o &lt;strong&gt;Netflix Eureka&lt;/strong&gt;, que mantém um catálogo dos serviços registrados:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ai-service
    ├── 10.0.1.20:8082
    └── 10.0.1.21:8082

payment-service
    └── 10.0.1.30:8083
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A aplicação conhece apenas o &lt;strong&gt;nome lógico&lt;/strong&gt; do serviço, que passa a representar sua identidade.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Spring Cloud OpenFeign
&lt;/h3&gt;

&lt;p&gt;O Spring Cloud OpenFeign permite representar chamadas HTTP como interfaces Java. Sem esse recurso, é necessário gerenciar manualmente URL, cabeçalhos, serialização, desserialização, métodos HTTP e tratamento de respostas:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;restClient&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;post&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;uri&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"http://ai-service/api/process"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;retrieve&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Com o OpenFeign, o contrato é declarado de forma explícita:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@FeignClient&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"ai-service"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;AiServiceClient&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@PostMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/api/v1/ai/process"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nc"&gt;AiResponse&lt;/span&gt; &lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@RequestBody&lt;/span&gt; &lt;span class="nc"&gt;AiRequest&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;AiServiceClient&lt;/span&gt; &lt;span class="n"&gt;aiServiceClient&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;AiRequest&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;AiResponse&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;aiServiceClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;process&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A chamada HTTP permanece, mas passa a ser expressa como um &lt;strong&gt;contrato Java&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Destaca-se a diferença entre os atributos &lt;code&gt;name&lt;/code&gt; e &lt;code&gt;url&lt;/code&gt;. Ao declarar &lt;code&gt;@FeignClient(name = "ai-service", url = "http://localhost:8082")&lt;/code&gt;, determina-se que o endereço especificado seja chamado diretamente. Ao declarar apenas &lt;code&gt;name&lt;/code&gt;, solicita-se ao mecanismo de descoberta que localize uma instância disponível do serviço. Embora a diferença sintática seja pequena, o impacto sobre o acoplamento é substancial.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Comunicação síncrona
&lt;/h3&gt;

&lt;p&gt;O OpenFeign é particularmente adequado à comunicação &lt;strong&gt;síncrona&lt;/strong&gt;, na qual a etapa seguinte depende da resposta anterior:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;UserDTO&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;userClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;findById&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isActive&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;BusinessException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Usuário inativo"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;continueProcessing&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nesse cenário, a conversão da chamada em evento não traria benefício evidente.&lt;/p&gt;

&lt;p&gt;A comunicação síncrona torna-se problemática quando a operação envolve múltiplas etapas demoradas. Considere-se um endpoint &lt;code&gt;POST /process-audio&lt;/code&gt; que deve: &lt;br&gt;
(1) enviar o arquivo a um modelo de IA; &lt;br&gt;
(2) aguardar a transcrição; &lt;br&gt;
(3) interpretar o texto; &lt;br&gt;
(4) consultar outro serviço; &lt;br&gt;
(5) executar uma operação; &lt;br&gt;
(6) gerar áudio; &lt;br&gt;
(7) retornar o resultado. &lt;/p&gt;

&lt;p&gt;A cadeia resultante é composta por chamadas síncronas encadeadas. Se cada serviço levar alguns segundos, a requisição original permanece aberta durante todo o processo. Torna-se, então, necessário avaliar se a operação realmente exige comportamento síncrono.&lt;/p&gt;
&lt;h3&gt;
  
  
  6. Comunicação assíncrona: webhooks e brokers
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Comunicação síncrona&lt;/strong&gt; (REST, OpenFeign, RestClient, WebClient) é adequada quando o resultado é necessário de imediato. Na &lt;strong&gt;comunicação assíncrona&lt;/strong&gt;, o serviço emissor publica um evento em um &lt;em&gt;message broker&lt;/em&gt; (RabbitMQ, Kafka, AWS SQS, Google Pub/Sub, entre outros) e prossegue sem aguardar o processamento pelo serviço receptor.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Webhooks&lt;/strong&gt; constituem outra forma de comunicação baseada em HTTP, com lógica distinta. Em vez de o cliente consultar repetidamente o estado da tarefa (&lt;em&gt;polling&lt;/em&gt;), o serviço responsável notifica o cliente ao término do processamento . Para uma tarefa de 20 segundos, o &lt;em&gt;polling&lt;/em&gt; exige sucessivas chamadas &lt;code&gt;GET /jobs/123&lt;/code&gt;. O webhook, por sua vez, envia o resultado por meio de &lt;code&gt;POST /webhooks/jobs/123&lt;/code&gt; quando este estiver disponível. Essa abordagem é vantajosa quando o processamento é demorado, quando o consumidor não deve permanecer bloqueado, quando há uma fronteira clara entre os serviços e quando o produtor é capaz de notificar o consumidor.&lt;/p&gt;

&lt;p&gt;É necessário, porém, distinguir webhooks de &lt;em&gt;message brokers&lt;/em&gt;. O webhook permanece uma comunicação HTTP direta entre dois serviços. O broker introduz uma camada intermediária que oferece persistência de mensagens, múltiplos consumidores, &lt;em&gt;retry&lt;/em&gt;, reprocessamento, desacoplamento temporal e controle de entrega. Assim, o webhook pode ser uma solução simples para determinadas integrações, ao passo que o broker é mais indicado para arquiteturas orientadas a eventos.&lt;/p&gt;
&lt;h3&gt;
  
  
  7. Arquitetura híbrida
&lt;/h3&gt;

&lt;p&gt;Os modelos síncrono e assíncrono não são excludentes e podem coexistir. A escolha deve considerar a natureza de cada operação:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;resposta necessária imediatamente: &lt;strong&gt;OpenFeign&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;continuidade possível sem a resposta: &lt;strong&gt;evento/fila&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;notificação de conclusão por sistema externo: &lt;strong&gt;webhook&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  8. Integração de serviços de inteligência artificial
&lt;/h3&gt;

&lt;p&gt;Uma aplicação moderna pode contar com um serviço especializado em IA. Nesse desenho, a &lt;strong&gt;API principal permanece responsável pelas regras de negócio&lt;/strong&gt;, enquanto o serviço de IA interpreta linguagem, processa áudio, gera texto e respostas e integra provedores de modelos. Essa separação cria uma fronteira bem definida. Por exemplo, a instrução "Crie uma despesa de R$ 40 no iFood" é interpretada pelo serviço de IA, convertida em um &lt;code&gt;CreateExpenseCommand&lt;/code&gt; e encaminhada à API principal, que aplica a regra de negócio e persiste o dado no PostgreSQL. O serviço de IA não acessa o banco de dados nem conhece a forma de persistência: limita-se a interpretar a intenção.&lt;/p&gt;

&lt;p&gt;Entre os provedores possíveis, o &lt;strong&gt;Google Gemini&lt;/strong&gt; mostra-se adequado a esse tipo de aplicação, sobretudo pela facilidade de integração via API e pela capacidade de processar diferentes tipos de entrada . O aspecto essencial, contudo, não é a escolha do provedor, mas evitar que o código de negócio dependa diretamente dele. A aplicação deve expressar a necessidade de "interpretar esta entrada", e não a de "chamar a API X neste ponto da regra de negócio".&lt;/p&gt;

&lt;p&gt;O &lt;strong&gt;Spring AI&lt;/strong&gt; contribui para esse objetivo ao oferecer abstrações, como o &lt;code&gt;ChatClient&lt;/code&gt;, que separam a configuração do modelo/provedor da lógica da aplicação:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;chatClient&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;prompt&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Analise esta mensagem..."&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;call&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Essa abordagem organiza a integração e torna menos invasiva a troca ou a experimentação de modelos, pois o código da aplicação não precisa lidar com os detalhes de HTTP, autenticação e formato de payload de cada provedor.&lt;/p&gt;

&lt;p&gt;A IA também pode operar em fluxos assíncronos. No processamento de áudio, em vez de o usuário aguardar a resposta completa, a API registra um &lt;em&gt;job&lt;/em&gt; em uma fila e retorna &lt;code&gt;202 Accepted&lt;/code&gt; com um &lt;code&gt;jobId&lt;/code&gt;. O serviço de IA processa a tarefa, consulta o Gemini e notifica a API por webhook ou evento, e a API, por fim, notifica o usuário.&lt;/p&gt;

&lt;h3&gt;
  
  
  9. Limites do OpenFeign e mecanismos de resiliência
&lt;/h3&gt;

&lt;p&gt;O OpenFeign resolve adequadamente a necessidade de invocar outro serviço HTTP, mas não é adequado a processamentos de longa duração. Tampouco resolve automaticamente idempotência, consistência distribuída, &lt;em&gt;retry&lt;/em&gt; seguro, &lt;em&gt;circuit breaker&lt;/em&gt;, filas, eventos, observabilidade ou transações distribuídas. Trata-se de uma ferramenta de comunicação, e não de uma arquitetura completa.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;9.1 Retry e idempotência.&lt;/strong&gt; Considere-se um &lt;code&gt;POST /payments&lt;/code&gt; invocado por um cliente Feign. Se a requisição alcançar o servidor e o pagamento for criado, mas a resposta se perder, o cliente pode interpretar o evento como falha. Um &lt;em&gt;retry&lt;/em&gt; automático geraria, nesse caso, um segundo pagamento. Chamadas que alteram estado devem, portanto, ser analisadas com cautela antes de receberem &lt;em&gt;retry&lt;/em&gt; automático. Uma solução recorrente é o uso de &lt;strong&gt;chaves de idempotência&lt;/strong&gt; (&lt;code&gt;Idempotency-Key: 8f3c...&lt;/code&gt;), que permitem ao servidor reconhecer operações já processadas.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;9.2 Timeout.&lt;/strong&gt; O tempo máximo de espera deve ser definido para cada dependência. Uma API interna pode operar com &lt;em&gt;connect timeout&lt;/em&gt; de 2 s e &lt;em&gt;read timeout&lt;/em&gt; de 5 s, enquanto uma chamada a um serviço de IA pode requerer 5 s e 60 s, respectivamente. Valores excessivos retêm recursos, e valores insuficientes convertem operações normais em erros. O &lt;em&gt;timeout&lt;/em&gt; é, portanto, parte do contrato da dependência, e não apenas um parâmetro de configuração.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;9.3 Circuit Breaker.&lt;/strong&gt; Se o Gemini estiver indisponível e a API persistir em novas tentativas, sucessivos &lt;em&gt;timeouts&lt;/em&gt; e &lt;em&gt;retries&lt;/em&gt; podem amplificar o problema. O &lt;em&gt;circuit breaker&lt;/em&gt; altera esse comportamento por meio de três estados: &lt;strong&gt;CLOSED&lt;/strong&gt;, no qual as chamadas ocorrem normalmente; &lt;strong&gt;OPEN&lt;/strong&gt;, alcançado após muitas falhas e no qual as requisições são rejeitadas rapidamente; e &lt;strong&gt;HALF-OPEN&lt;/strong&gt;, no qual uma chamada de teste é realizada e, se bem-sucedida, restaura o estado CLOSED. Isso evita sobrecarregar uma dependência já em falha.&lt;/p&gt;

&lt;h3&gt;
  
  
  10. Visão integrada
&lt;/h3&gt;

&lt;p&gt;A Figura apresenta a arquitetura completa, e a Tabela 1 sintetiza as estratégias discutidas.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tabela 1.&lt;/strong&gt; Estratégias de comunicação segundo a situação.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Situação&lt;/th&gt;
&lt;th&gt;Estratégia&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;API precisa da resposta imediatamente&lt;/td&gt;
&lt;td&gt;OpenFeign&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Serviço precisa localizar outra instância&lt;/td&gt;
&lt;td&gt;Service Discovery&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Operação demorada&lt;/td&gt;
&lt;td&gt;Assíncrono&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sistema externo precisa notificar a conclusão&lt;/td&gt;
&lt;td&gt;Webhook&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vários consumidores precisam receber o evento&lt;/td&gt;
&lt;td&gt;Message Broker&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Integração com LLM&lt;/td&gt;
&lt;td&gt;Spring AI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dependência instável&lt;/td&gt;
&lt;td&gt;Timeout + Circuit Breaker&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Operação passível de repetição&lt;/td&gt;
&lt;td&gt;Idempotência&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  11. Critérios de decisão
&lt;/h3&gt;

&lt;p&gt;Com base na experiência de desenvolvimento de uma aplicação SaaS, a escolha da estratégia de comunicação pode ser orientada por quatro perguntas:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;A resposta é necessária de imediato?&lt;/strong&gt; Em caso afirmativo, utiliza-se HTTP/OpenFeign.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;É possível prosseguir sem essa resposta?&lt;/strong&gt; Em caso afirmativo, utiliza-se evento/fila.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quem saberá quando o processamento terminar?&lt;/strong&gt; Se for outro sistema, utiliza-se webhook.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A operação pode ser executada mais de uma vez?&lt;/strong&gt; Em caso afirmativo, deve-se garantir idempotência.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A última pergunta é particularmente relevante em sistemas distribuídos, nos quais falhas parciais passam a integrar o comportamento normal do sistema.&lt;/p&gt;

&lt;h3&gt;
  
  
  12. Implicações da transição de um monólito
&lt;/h3&gt;

&lt;p&gt;A principal mudança na transição de um monólito não é a existência de múltiplos projetos Spring Boot, mas a aceitação de &lt;strong&gt;falhas intermediárias&lt;/strong&gt;. Em um monólito, o fluxo é linear (Controller → Service → Repository → Database). Em uma arquitetura distribuída, o fluxo atravessa múltiplas fronteiras de rede (Controller → Service A → HTTP → Service B → HTTP → Service C), e cada etapa pode falhar de forma independente. Os serviços A e B podem estar operacionais e, ainda assim, a rede entre eles pode estar indisponível. Esse tipo de problema raramente é evidenciado quando os microsserviços são estudados apenas por meio de diagramas.&lt;/p&gt;

&lt;h3&gt;
  
  
  13. Conclusão
&lt;/h3&gt;

&lt;p&gt;A adoção de microsserviços não se resume à divisão de uma aplicação em vários projetos. A existência de múltiplos processos exige atenção a &lt;strong&gt;comunicação, descoberta de serviços, &lt;em&gt;timeout&lt;/em&gt;, falhas, idempotência e consistência&lt;/strong&gt;. O Spring Cloud oferece ferramentas relevantes nesse sentido: o &lt;strong&gt;OpenFeign&lt;/strong&gt; simplifica as chamadas HTTP entre serviços, o &lt;strong&gt;Service Discovery&lt;/strong&gt; elimina o acoplamento a endereços físicos, o &lt;strong&gt;LoadBalancer&lt;/strong&gt; viabiliza o uso de múltiplas instâncias, &lt;strong&gt;webhooks e eventos&lt;/strong&gt; retiram operações demoradas do caminho síncrono, e o &lt;strong&gt;Spring AI&lt;/strong&gt; facilita a integração com modelos de IA, incluindo o Gemini. Os mecanismos de resiliência, por sua vez, permitem lidar com o fato inevitável de que, em um sistema distribuído, falhas ocorrerão.&lt;/p&gt;

&lt;p&gt;Conclui-se que a escolha entre comunicação síncrona, assíncrona, OpenFeign, webhooks ou mensageria deve ser orientada pela &lt;strong&gt;dependência entre as etapas do negócio&lt;/strong&gt;, e não pela sofisticação aparente da tecnologia. Se a etapa seguinte depende da resposta, a chamada síncrona é adequada. Se pode aguardar, um evento tende a ser preferível. Se um sistema externo notifica a conclusão, o webhook pode simplificar a arquitetura.&lt;/p&gt;

&lt;p&gt;Por fim, os microsserviços não eliminam o acoplamento: eles o transformam de &lt;strong&gt;acoplamento de código em acoplamento de comunicação&lt;/strong&gt;, o que exige que essa comunicação seja projetada de forma deliberada.&lt;/p&gt;




</description>
      <category>ai</category>
      <category>programming</category>
      <category>webdev</category>
      <category>architecture</category>
    </item>
  </channel>
</rss>
