{"id":24490208,"url":"https://github.com/zenonxd/microservices-study","last_synced_at":"2025-08-04T15:33:54.725Z","repository":{"id":271609992,"uuid":"913415626","full_name":"zenonxd/microservices-study","owner":"zenonxd","description":"Estudo visando descomplicar microserviços.","archived":false,"fork":false,"pushed_at":"2025-01-08T19:03:01.000Z","size":1589,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-01-21T17:17:22.721Z","etag":null,"topics":["eventdriven","eventdrivenarchitecture","eventsourcing","microservice","microservices","microservices-architecture","saga-pattern"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zenonxd.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-01-07T16:34:09.000Z","updated_at":"2025-01-08T19:07:10.000Z","dependencies_parsed_at":"2025-01-08T20:22:48.389Z","dependency_job_id":"7cb1f425-7390-4ded-8a24-589731631938","html_url":"https://github.com/zenonxd/microservices-study","commit_stats":null,"previous_names":["zenonxd/microservices-study"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zenonxd%2Fmicroservices-study","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zenonxd%2Fmicroservices-study/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zenonxd%2Fmicroservices-study/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zenonxd%2Fmicroservices-study/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zenonxd","download_url":"https://codeload.github.com/zenonxd/microservices-study/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243670259,"owners_count":20328433,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["eventdriven","eventdrivenarchitecture","eventsourcing","microservice","microservices","microservices-architecture","saga-pattern"],"created_at":"2025-01-21T17:17:25.177Z","updated_at":"2025-03-15T01:26:44.136Z","avatar_url":"https://github.com/zenonxd.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# About\n\nEstudo sobre Microservices, juntamente com uma visão geral de padrão de projeto e arquitetura.\n\n[Link Notion Giu Bezerra](https://giulianabezerra.notion.site/Descomplicando-Microsservi-os-7c267aca56664c0d95cb072cfcc9798f)\n\n[Video](https://www.youtube.com/watch?v=5POMDqQw8hQ)\n\n# O que são microservices\n\n![img.png](img.png)\n\nSeria uma visão macro, e dentro da solução do microservice, teríamos a aplicação de alguns **patterns**. Iremos entrar\nmais a fundo sobre eles ja já!\n\nComo podemos ver na imagem acima, temos vários serviços desacoplados (independentes entre sí), responsáveis por um \ncontexto de negócio! Neste caso, um e-commerce.\n\nPortanto, são **serviços menores, desacoplados e independentes** (**modulares**). **Paralelizam desenvolvimento**, **diferentes pilhas\ntecnológicas**, são serviços **escaláveis**, com **responsabilidade limitada**, **cloud-ready** (Spring Boot + Spring Cloud).\n\nVamos agora adentrar nesse parágrafo ⬆️ e entender alguns pontos.\n\n## Paralelizar desenvolvimento\n\nNo contexto de microsserviços, seria a capacidade de trabalhar em diferentes partes de um sistema de forma simultânea e\nindependente.\n\nOu seja, ao invés de termos uma **única** aplicação monolítica, exigindo que todos os desenvolvedores trabalhem juntos\nna mesma base de código e no mesmo processo de desenvolvimento, os microsserviços permitem que equipes distintas **possam\ntrabalhar em diferentes serviços de uma maneira isolada**, mas que, no final, colaboram entre sí para formar um sistema\ncompleto.\n\nUm adendo: cada equipe pode trabalhar no serviço que é responsável, utilizando diferentes tecnologias.\n\n## Serviços menores, desacoplados e independentes\n\nCada microsserviço é uma parte pequena e independente de um sistema maior, focando em uma só responsabilidade.\n\nEles são **desacoplados**, ou seja, não dependem diretamente uns dos outros para funcionar. \n\nIsso permite que eles sejam modificados e implantados de maneira independente.\n\n## Modulares\n\nComo os microsserviços são pequenos e focados em uma única funcionalidade, eles são altamente **modulares**.\n\nIsso significa que podem ser: desenvolvidos, testados, implantados e escalados **SEPARADAMENTE**.\n\n## Diferentes pilhas tecnológicas\n\nComo cada microsserviço é independente, ele pode ser desenvolvido utilizando diferentes tecnologias (conforme citados no\nparalelismo).\n\nIsso engloba: linguagens de programação, banco de dados e frameworks, acaba dependendo da necessidade do serviço.\n\nPor exemplo, um microsserviço pode ser feito em Java, outro em Node.js e outro em Python e tudo isso dentro do mesmo\nsistema, exatamente como podemos ver na imagem acima! Alguns feitos com Java, Outro com PHP e por aí vai.\n\n## Escalável\n\nMicrosserviços podem ser escalados de forma independente, ou seja, caso um serviço precise de mais recursos devido a \naumento de carga, ele pode ser escalado sem afetar outros serviços.\n\nOu seja, um sistema escalável pode crescer ou ser ajustado conforme a necessidade, seja aumentando recurso ou distribuindo\ncarga de maneira inteligente.\n\n## Responsabilidade limitada\n\nCada microsserviço tem uma única responsabilidade ou função específica. Isso acaba tornando o código mais claro e fácil\nde manter.\n\n## Cloud ready\n\nMicrosserviços são ideais para ambientes em nuvem (cloud), pois podem ser facilmente distribuídos, escalados e \ngerenciados usando plataformas de nuvem.\n\n## Spring Boot + Spring Cloud\n\nEssas são ferramentes do ecossistema Java que facilitam o desenvolvimento de microsserviços.\n\nO Spring Boot simplifica a criação de aplicações Java independentes e prontas para produção.\n\nJá o Spring Cloud, oferece funcionalidades para gerenciar microsserviços distribuídos, como: configuração centralizada,\ndescoberta de serviços, tolerância a falhas, etc.\n\n# Comunicação entre microsserviços\n\nBom, aos realizarmos a separação dos microsserviços, temos alguns pontos que precisam ser tratados para que eles possam\nse comunicar.\n\nPara isso, existem alguns patterns que podemos aplicar para resolver esses problemas de arquitetura que vão aparecendo\nao separar serviços.\n\n## HTTP Protocol\n\nAntes de falarmos sobre os patterns, vamos abordar brevemente o protocolo HTTP!\n\nVárias aplicações, cada um com seu banco de dados.\n\nAntes ficava tudo no mesmo pacote (quando se é monolítico), correto? O OrderService chamava o OrderShipping e por aí vai...\n\nComo agora temos vários serviços e estão separados, precisamos nos comunicar **PELA REDE**, pois são sistemas distribuídos.\n\nPara realizarmos essa comunicação via HTTP, cada serviço precisa estar em uma porta específica, veja:\n\n![img_1.png](img_1.png)\n\nO problema desse esquema não monolítico é o seguinte: como fazer para organizar essas múltiplas chamadas pela rede,\ngerenciando esses endereços de forma mais simples? Agora, sim, veremos um pattern: **API Gateway**.\n\n## 1º Pattern, API Gateway - Simplificando chamadas\n\nÉ usado como ponto central de acesso para roteamento entre vários microsserviços. A gente coloca ele no meio para lidar\ncom essas chamadas.\n\n![img_2.png](img_2.png)\n\nEntão a ideia agora é a seguinte: antes, o nosso SPA (o frontend) chamava os serviços diretamente. Agora, ele passa a\nchamar um recurso do gateway (não mais os serviços diretamente).\n\nEntão se ele recebe um recurso para \"/orders\", encaminharemos a requisição para o serviço de pedidos (OrderService).\n\nExatamente como citamos acima, o gateway é um ponto central para acessarmos os microsserviços, minimizando aquela bagunça\ndo frontend fazendo chamada para todo mundo.\n\nFrisando, pode-se ver na imagem que o gateway possui as rotas para os microsserviços: \"/order, /inventory\". Ele acaba\nfuncionando como um \"mapa\" de endereços.\n\n**❗Um problema! Até aqui, nós centralizamos os endereços no API Gateway, mas nós só mudamos a gerência dos endereços!**\n\nO Gateway ainda precisa saber os DNS e portas dos serviços, lidando com as informações ⬇️.\n\n## 2º Pattern, Service Discovery\n\nPara o nosso Gateway saber onde fica os microsserviços, ele irá consultar um **Service Discovery**. Ele irá possuir os \ndados de TODOS os microsserviços e instâncias que estão rodando, **como se fosse uma agenda telefônica.**\n\nCada microsserviço irá se registrar nele assim que fica no ar.\n\n![img_3.png](img_3.png)\n\nImagine que a gente faça uma requisição solicitando um recurso em \"/orders\", por exemplo. O Service Discovery vai nos\nresponder, apontando para o microsserviço correspondente.\n\n### Como o Service Discovery sabe dos endereços baseado nos recursos?\n\nEle sabe porque todos os microsserviços quando se iniciam, são registrados nele!\n\nEntão até o momento, centralizamos também o gerenciamento de endereços em um componente que só tem essa responsabilidade!\n\n[Aprenda a implementar o Service Discovery com Eureka e Spring Cloud Gateway](https://www.youtube.com/watch?v=ju7NTqJxKRs)\n\nMais um problema resolvido, correto? Mas ainda temos alguns problemas com essa arquitetura: e se houver mais instâncias\ndo mesmo serviço? Trabalharemos com o Load Balancer Pattern. ⬇️\n\n## 3º Pattern, Load Balancer\n\nNo mundo real temos mais de uma instância para ter redundância nas respostas dos microsserviços. Mas com mais de uma\ninstância, como saberemos QUEM chamar? QUEM está desocupado?\n\nO Load Balancer, é um **balanceador de carga**, responsável por fazer requisições à diferentes instâncias de um mesmo \nmicrosserviço. **Ele vai direcionar as requisições que irão chegar para diferentes instâncias do MESMO serviço**.\n\n![img_4.png](img_4.png)\n\n**Observe na imagem que agora temos várias instancias rodando ao mesmo tempo! Uma com 3, outra com duas...**\n\nE agora também não temos mais a ideia de acessar o endereço e uma porta específica. Se você reparar nas imagens acima\nanteriormente estávamos acessando, por exemplo ``order:8080``. \n\nAgora, o Gateway chama o Load Balancer e ele por sua vez, direciona para a porta correta: ``order:port``.\n\nFrisando que o Load Balancer faz um trabalho de \"Round Robin\". Ou seja, a primeira requisição vai para a primeira \ninstância e assim sucessivamente.\n\n## 4º Pattern, Centralized Configuration\n\nCada um dos nossos serviços tem suas configurações. Como estamos lidando com Spring Boot, a gente utiliza o ``application.properties``.\nPara lidar com acesso a banco, endereço de serviços externos, etc.\n\nPorém, com um grande número de microsserviços, temos um grande número de arquivos de configuração.\n\nEsse pattern será responsável por gerenciar essas configurações. Utilizaremos um \"Config Server\", um componente, onde\nirá centralizar todos os arquivos de configuração, e ainda será possível atualizar as props sem derrubar os microsserviços.\n\n![img_5.png](img_5.png)\n\nEsse componente ``Config Server``, levará até mesmo o arquivo de configuração do Gateway.\n\nE é conforme citamos acima, com esses arquivos centralizados em um só local, é mais fácil de ajustar o que for necessário,\nsem afetar o programa.\n\n## Alternativa para uso de HTTP? \n\nSabemos que o HTTP é uma relação síncrona, ou seja, nosso SPA (frontend) vai esperar as chamadas serem respondidas\ne teremos algumas esperas se tivermos chamadas entre serviços (essas chamadas também são síncronas).\n\nIsso compromete a disponibilidade do nosso sistema. Se um serviço cai, será que precisamos tornar todo o e-commerce\nindisponível?\n\nEntão temos outras formas de comunicação entre serviços além da inter service (serviço para serviço de forma síncrona).\n\nAí que vem o Event Driven. ⬇️\n\n## 5º Pattern, Event Driven PUB/SUB\n\nA ideia é que a gente utilize uma conexão baseada em **eventos**.\n\nAntes, tínhamos requisições sendo feitas diretamente, chegando no SPA, indo para o Gateway, depois orquestrando uma\nrequisição por vez...\n\nAgora faremos o mínimo de chamadas possível via Gateway, e as outras etapas de comunicação podemos fazer via Message\nBroker, conforme podemos ver pela imagem abaixo.\n\n![img_6.png](img_6.png)\n\nMessage Broker é um enviador e recebedor de mensagens. Por exemplo, quando um pedido é feito, a gente pode notificar\no sistema de pagamento.\n\nMas não precisa chamar o sistema de pagamento direto, a gente pode mandar uma mensagem e quando o sistema de pagamento\nreceber uma mensagem desse tipo ele já vai ficar \"ouvindo\", para que ele possa trabalhar/processar.\n\nE por sua vez, esse sistema de pagamento, ao começar a processar, poderá enviar OUTRA message para outro service.\n\nVocê pode observar isso na imagem acima. As setas são bidirecionais, assim como recebem mensagens, as envia de volta...\ntudo isso de forma assíncrona!\n\nOu seja, se um serviço fica momentaneamente de fora, quando ele voltar ao ar, poderá buscar a mensagem recebida e \nprocessá-la de acordo.\n\nEsse modelo também é chamado de PUB/SUB. Visto que, alguém publica uma mensagem no broker (PUB) e alguém se inscreve\npara recebê-las (SUB).\n\n### Tipos de mensagens\n\nQuery - Consulta, retornar dado correspondente.\n\nCommand - Fazer algo, processamento. Criar registro, atualizar, etc.\n\nEvent - Notificação para interessados em fazer algo a respeito, processar algo que é responsabilidade dela.\n\nEntão podemos, dependendo do tipo da mensagem, criar um fluxo completo para cada funcionalidade do sistema.\n\nDesde fazer um pedido, até ativar o pagamento desse pedido, o serviço de entrega... tudo será orquestrado por essa\ncomunicação assíncrona através de mensagens específicas enviadas ao Message Broker.\n\nCom esse processamento assíncrono, trabalharemos com um conceito super importante: Consistência Eventual.\n\n### Consistência Eventual\n\nNesse modelo atual, significa que em algum momento, eventual o pedido será feito, o pagamento ativado com enviado de \ne-mail, ele será eventualmente **COMPLETO**.\n\nNós falamos eventual porque é um processo assíncrono, não sabemos QUANDO, mas sabemos que será finalizado, depende de cada\nserviço fazendo seu trabalho.\n\n## Outros Patterns\n\nTemos também outros padrões, como: Distributed Tracing, Circuit Breaker, Access Token, você pode checá-los esses e \noutros [aqui](https://microservices.io/patterns/index.html).\n\n# Visão Dados\n\nAgora que falamos de aplicação, falaremos dos dados!\n\nPatterns que se relacionam com a forma que os dados são criados/manipulados dentro de um banco de dados. Um dos patterns\nque atende essa necessidade é o **Event Sourcing, advindo do Event Driven**. ⬇️\n\n## Event Sourcing\n\nImagine que temos um Record, um User. Em um sistema tradicional, alguém manda uma requisição POST para criar um Usuário,\nele vai para o banco de dados com todas as informações, e nós salvamos ele completo no banco de dados.\n\nJá no Event Sourcing, ao invés de criar um registro e salvá-lo por completo, nós salvamos os eventos com as mudanças\nnecessárias para construir esse estado.\n\nEntão ao invés de salvar ``login, email, password``, salvaríamos um evento de ``USER CREATED``, com as informações da\ncriação do usuário para que eventualmente possamos reproduzí-la.\n\nSe fosse um update, por exemplo, poderíamos salvar só o item atualizado. Se só a senha mudou, manter somente o registro\nda nova senha.\n\n![img_7.png](img_7.png)\n\nComo podemos ver na imagem acima, temos 3 eventos disparados: created, updated e deleted.\n\nEsses eventos são enviados para o service, processados e enviados para uma ``Event Store``. Com os eventos processados\nenviamos para um barramento de eventos ``Eventbus`` (basicamente o Message Broker), precisa ser alguém que receba\nos eventos de forma assíncrona.\n\nE por fim, teremos uma base de dados que terá o estado final do registro, que irá consumir os eventos e construir o item \nfinal.\n\nNo nosso caso, se executarmos na ordem os 3 eventos disparados, teremos um item com status ``deleted``. E sim, ele terá\nos dados da criação e da atualização que aconteceu antes do delete.\n\nPortanto: para saber o estado final do item, precisamos só executar a sequência de eventos.\n\nIsso é importante, porque esses eventos são **IMUTÁVEIS**. Então se tivermos um cenário de perda/deleção, podemos\nreproduzir os eventos, pegando o ÚLTIMO estado consistente! É mais difícil de perder a integridade dos dados.\n\nPor isso algumas aplicações é interessante usar o Event Sourcing (advindo do Event Driven).\n\n**Caso trocássemos de banco, é a mesma coisa... é só dar um replay nos eventos e construir o item final.**\n\n## Command Query Responsibility Segregation - CQRS\n\nEstratégia constantemente utilizada com o Event Sourcing. \n\nPor exemplo, se temos uma base de dados que está otimizada para leitura, geralmente aplicamos índices para otimizar esse\nprocesso de leitura, correto? Mas se quiséssemos depois otimizar para escrita, teríamos que remover esses indices para que\na escrita seja mais rápida, onde, por sua vez, iríamos prejudicar a leitura.\n\nA idéia é separar os comandos de processamento dos comandos de consulta, separando as responsabilidades e, consequentemente,\notimizando o serviço.\n\nPossui operações básicas, tais como:\n\n- Commandos (escritas), são trigger actions, que acabam mudando o estado da aplicação\n\n\n- Queries (leituras), basicamente retorno de informação - find, get...\n\n\n- Event (notificação de algo que aconteceu)\n\nPossui também um microsserviço cuidando de ambas operações (ou dois), um para cada operação e com seu próprio banco\nde dados.\n\nO banco pode ser otimizado para escrita ou leitura, dependendo do microsserviço (se ele é command ou query).\n\nPara sincronizar os bancos, esses eventos de escrita são enviados para uma fila de mensagem (pelo commands handler), que\npor sua vez, será consumido pelo Event Handler do Query Microservice.\n\nE como citamos, geralmente esse pattern é usado com Event Sourcing.\n\n![img_8.png](img_8.png)\n\nDo lado esquerdo, temos o command (escrita), logo, os estados/eventos.\n\nDo lado direito, temos a query, o registro final que pode ser consultado.\n\nEsse broker no meio, nos auxilia a sincronizar os dados, gerados pelos eventos (lado esquerdo), publicados no broker que\npor sua vez, são consumidos pelo banco de leitura.\n\n## SAGA Pattern - Visão de transação  \n\nVamos relembrar uma coisa. Antes de separarmos os serviços, eles estavam no contexto de uma transação somente.\n\nAssim que os separamos, nós precisamos trazer uma visão de transação diferente, visto que agora os serviços estão\nseparados na rede.\n\nEntão ao invés de termos somente UMA transação global, tipo: fazer pedido \u003e pagamento \u003e shipping \u003e e-mail.\n\nTeremos várias sub transações que irão pertencer a nossa **saga** e caso alguma delas falhe, simplesmente fazemos um\nrollback de tudo. **Esse rollback é feito com transações compensatórias**.\n\n![img_9.png](img_9.png)\n\nVeja na imagem acima. Na parte da direita, o quinto evento não foi concluído. Portanto, nós consumimos esse evento que\ndeu problema e cada um dos serviços anteriores que estão lidando com seu respectivo evento, terão que dar rollback (sua \ntransação compensatória).\n\nMas podemos ter diferentes tipos de saga, a **coreografada** e **orquestrada**, veja:\n\n### Orquestrada\n\nVeja a imagem no lado esquerdo, o próprio serviço (orquestrador da saga) gera os eventos, mesmo sendo serviços diferentes\nA e B.\n\n### Coreografada\n\nNós não teríamos um serviço orquestrador. Ao invés disto, cada serviço será responsável por gerar seus eventos dentro da\nsaga.\n\n### Qual escolher?\n\nA orquestrada geralmente é mais interessante, pois nos dá uma visão mais global da saga e fica mais fácil de manter, pois\ntudo fica lá.\n\nSe a gente realiza muito desacoplamento, espalha a geração de eventos e fica difícil ter uma visão mais global.\n\nCom a orquestrada se ocorre algum problema, fica mais fácil saber onde ele ocorreu e corrigir.\n\n❗Entretanto, importante: para escolher o melhor tipo de saga, estude seu sistema, entenda a arquitetura do mesmo, quantos\neventos ou serviços ele irá possuir, etc.\n\n# Resumo\n\nNo tocante a aplicação, a idéia é separar nossos serviços usando a arquitetura Event Driven (utilizada para \ndesacoplá-los ainda mais).\n\nJá na parte de dados, utilizando CQRS com Event Sourcing para otimizar a leitura e escrita.\n\nE por fim a transação. Antes de separarmos os serviços, eles estavam no contexto de uma só transação. Com eles separados,\nprecisamos trazer uma visão de transação para serviços que estão separados na rede (utilizando SAGA Pattern).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzenonxd%2Fmicroservices-study","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzenonxd%2Fmicroservices-study","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzenonxd%2Fmicroservices-study/lists"}