Você tem microsserviços ou só fez um monólito picotado?
O que é um microsserviço de verdade?
Microsserviços são unidades independentes de software que seguem o princípio de responsabilidade única, possuem seus próprios bancos de dados, podem ser implantados separadamente e se comunicam via APIs bem definidas, geralmente de forma assíncrona. O objetivo é melhorar escalabilidade, manutenção e resiliência.
Mas aí vem o problema: muita gente acha que microsserviço é simplesmente quebrar um monólito em várias partes e colocar cada uma em um container. Isso não só não resolve nada, como pode piorar o sistema inteiro. Vamos falar sobre os erros mais comuns.
1. Microsserviço ≠ Container
Colocar um monstro de código dentro de um container e chamar de microsserviço é autoengano. Microsserviços são independentes, têm fronteiras bem definidas e são implantados separadamente. Se você tem que subir tudo junto para funcionar, parabéns, você apenas fatiou seu monólito sem nenhum ganho real.
2. Acoplamento disfarçado
Se você precisa atualizar e fazer deploy de vários "microsserviços" ao mesmo tempo para evitar quebra, você não tem microsserviços, tem um Frankenstein com endpoints. Se um serviço caído paralisa o sistema inteiro, você criou um castelo de cartas distribuído. Microsserviços de verdade são independentes e resilientes.
3. Banco de dados compartilhado é um atestado de incompetência
Se todos os seus "microsserviços" estão pendurados no mesmo banco de dados monolítico, você construiu um monstro ainda pior que o monólito original. Cada serviço precisa ser dono do seu próprio banco. Quer consistência? Use eventos e comunicação assíncrona. Caso contrário, não se iluda, você só separou seu monólito em peças sem vantagem nenhuma.
4. Orquestração vs. Coreografia
Se sua aplicação depende de chamadas cascata entre 10 serviços só para uma resposta, você não construiu microsserviços, você construiu um inferno de latência e pontos de falha. Microsserviços bem feitos usam eventos, mensageria (Kafka, RabbitMQ) e evitam esse caos.
5. Monitoramento e observabilidade não são frescura
Separou tudo em serviços, mas não tem logs centralizados? Não tem tracing distribuído? Boa sorte achando onde está o erro quando der pau. Se você acha que microsserviço significa só quebrar código em vários repositórios sem visibilidade, você está brincando de engenharia.
6. O custo de microsserviços
Microsserviços têm um custo real: infraestrutura distribuída, pipelines de CI/CD separados, gestão de logs e segurança em escala. Se seu sistema não tem demanda real para isso, um monólito bem arquitetado é uma escolha muito mais sensata.
Conclusão
Microsserviços de verdade exigem planejamento, boas práticas e uma arquitetura decente. Se você só colocou seu monólito dentro de containers e distribuiu pelo cluster, você se enganou e ainda tornou sua própria vida mais difícil. Antes de sair quebrando tudo em serviços, pergunte-se: você quer resolver um problema real ou só quer seguir uma modinha sem entender o que está fazendo?
Microsserviços não precisam seguir o princípio da responsabilidade única, até porque isso é um pouco vago, só é famoso por causa do Uncle Bob e outros que se destacaram na área, e se for responsabilidade única no mesmo sentido S de SOLID, é tão pouco que teria que chamar de picosserviços, porque seria equivalente a uma função simples.
Tem-se a ideia que microsserviços precisa fazer poucas coisas, mas não há uma definição clara do que é pouco. A ideia principal é o desacoplamento, não da responsabilidade.
E é bom entender que um microsserviço não tem nada de mais. Ou que queria chamar de macrosserviço porque faz muitas coisas, mas é um serviço isolado e independente. Se você fizer um software que se comunica como o Facebook ele poderia ser um serviço (micro, midi, macro, não importa) da plataforma do Facebook. E isso é uma utilização que faz todo sentido.
O mesmo se aplica para serviços independentes e isolado dentro de uma empresa, cada unidade atua no desenvolvimento dos seus softwares do que jeito que bem entendem sem se preocupar muito com o que outras unidades estão fazendo. O que ela tem de compromisso é que se alguém precisa de uma informação que é propriedade daquela unidade será disponibilizada uma API para informar mudanças e outras unidades pegarem o que precisam ou foi mudado na sua unidade. Em tese essa API precisa ser estável, mas pode ter regras para quebrar a compatibilidade, desde que bem documentado com antecedência (geralmente).
A arquitetura de microsserviços que é mais do que apenas criar um ou mais microsserviços, é pensar que toda infraestrutura de software da empresa seja desacoplada e as se garanta que as unidades sejam livres para fazer o que quiserem dentro do seu domínio. A arquitetura é toda pensada assim. Do ponto de vista externo uma unidade só precisa garantir que todas as unidades possam ser servidas no que precisam, até mesmo envolvendo seu microsserviço em uma transação completa e talvez complexa.
Quero reforçar que nem sempre é assíncrona, embora o texto já tenha dito isso, pode não ficar claro para todos, existem situação que não pode ser assim, até porque pode não suportar consistência eventual, então ele ganha isso er abre mão da disponibilidade (a partição está lá sempre por definição no caso de microsserviços). Veja sobre Teorema CAP.
É possível ter ganho real com monólitos distribuídos pu só quebrados, só não são microsserviços.
Fazer microsserviços realmente resilientes tem uma complexidade que poucos conseguem executar, por isso é comum deixarem isso um pouco de lado, e vemos "frequentemente" quem adotou microsserviços saindo do ar.
De fato fazer a comunicação via banco de dados é um erro e acopla, o que deixa de ser microsserviços. Fazer tudo desacoplado de verdade, e pior, mantendo a coesão é um enorme desafio e o normal é encontrar arquiteturas cheias de falhas que podem aparecer com mais ou menos frequência (tem lugar que eu acesso e já sei que é microsserviços pelas falhas, geralmente momentâneas, que vejo ou pela lentidão de resposta (que pode ser outros fatores), ou não é arquitetura real de microsserviços.
Curiosamente é que a maioria dos microsserviços, se forem assim mesmo, podem rodar SQLite como banco de dados, de tão simples que fica o microsserviço em si (o problema é a integração entre eles). E por isso que muita gente usa MongoDB, ele pode não ser a melhor solução, mas é mais uma modinha a seguir, e de tão simples que fica que até ele serve muito bem, mesmo quando não for o mais adequado (tem casos que ele pode ser a melhor opção).
Não sei se o encadeamento grande faz a arquitetura deixar de ser de microsserviços, mas que é ruim eu não tenho dúvida.
No caso da observabilidade não tem relação com microsserviços, embora com eles se torna fundamental ter algo bem implementando nesse sentido.
Quase ninguém precisa de uma arquitetura de microsserviços, do ponto de vista de escala, sempre dá para escalar com arquiteturas mais simples, e do ponto de vista organizacional pode ser útil ou não. Microsserviços é complexo demais, quase ninguém faz direito, custa muito mais caro em termos financeiros seja na implementação, seja na execução e traz algumas desvantagens relevantes em muitos cenários.
Aí cabe a imagem famosa, que apesar de ser jocosa é muito real, e talvez por ser engraçada as pessoas não levam tanto a sério. Faça seu monólito bem-feito, se realmente puder provar que ainda precisa de microsserviços depois disso, então comece fazer alguns experimentos para ver se dará o resultado que espera.
Arquitetura de microsserviços é uma das maiores modinhas que já apareceu.
S2
Farei algo que muitos pedem para aprender a programar corretamente, gratuitamente (não vendo nada, é retribuição na minha aposentadoria) (links aqui no perfil também).
Mandou bem demais nesse post! Você tocou nuns pontos que doem em muita gente. É que a modinha dos microsserviços pegou forte, né? Muita gente ouviu falar, viu palestra, achou moderno e saiu correndo pra quebrar o sistema antigo em pedacinhos, achando que isso era "evoluir".
O problema é que, como você mostrou, muitas vezes essa pressa pra seguir a tendência, sem parar pra pensar direito, acaba criando os problemas que você listou: serviço que depende do outro pra tudo, todo mundo usando o mesmo banco de dados, uma confusão pra chamar as coisas, ninguém sabendo onde deu erro... Troca-se um problema conhecido por vários novos e escondidos!
Isso mostra que talvez o X da questão nem fosse o sistema antigo (o monólito). Talvez o problema real fosse a falta de organização, a gente não ter parado pra definir direitinho o que cada parte faz e, principalmente, se o time e a empresa estavam prontos pra essa confusão toda que é gerenciar um monte de coisa separada.
Aí fico pensando umas coisas aqui pra gente discutir, especialmente por causa dessa febre dos microsserviços:
Pra quê mesmo? Era necessidade ou só vontade de estar na moda? Antes de sair quebrando tudo, qual era o incômodo real? Precisava mesmo dessa separação toda pra escalar uma parte específica? Ou pra cada time trabalhar de boa no seu canto? Ou foi mais pra seguir a onda, botar no currículo, ou tentar fugir de um código velho sem querer ter o trabalho de arrumar ele de verdade? Bagunça no time = Bagunça no código? Será que essa dificuldade de fazer os serviços ficarem independentes não é culpa do jeito que a galera se organiza? Se cada time não sabe direito do que é dono, como é que o serviço vai ser independente? A arquitetura do código muitas vezes vira o espelho da organização (ou desorganização) da empresa. E a dor de cabeça que ninguém conta? A gente fala do custo de servidor, de nuvem... mas e o custo de quebrar a cabeça pra entender como tudo funciona junto? Pra achar um erro que passa por vários serviços? A galera que vende a ideia do microsserviço como solução pra tudo esquece de avisar o tamanho dessa encrenca no dia a dia? Tentamos arrumar a casa antes de demolir? E os gigantes que ainda usam monólito? Antes de meter a marreta no sistema antigo só porque "monólito é feio" na modinha, a gente tentou dar uma organizada nele? Separar as coisas dentro dele mesmo (o tal do Monólito Modular), melhorar os testes? Às vezes, um sistema antigo bem arrumadinho dá menos trabalho e custa menos. E ó, não é vergonha nenhuma! Pensa em empresas gigantes como o Shopify, que você mencionou. Eles rodam uma plataforma enorme, em grande parte, num monólito Ruby on Rails e dão conta do recado (e como!). Outros exemplos são o GitHub, o Stack Overflow, o Basecamp... todos eles têm arquiteturas com monólitos fortes no centro do negócio e são super bem-sucedidos. Eles provam que um monólito bem feito e bem cuidado pode ir muito longe, talvez até mais do que um monte de microsserviços bagunçados feitos na correria.
No fim das contas, valeu a pena o "hype"? Essa trabalheira toda com serviços separados tá realmente ajudando a empresa (entregando mais rápido, aguentando mais gente usando, etc.) ou só complicou a vida de quem desenvolve e aumentou os custos pra poder dizer que usa "arquitetura moderna", enquanto outros gigantes continuam firmes e fortes com seus monólitos?
Seu post deu um belo sacode na galera! Talvez a pergunta não seja só "você tem microsserviços ou só um monte de pedaços do sistema antigo?", mas também "Por que a gente entrou nessa? Foi por necessidade real ou só pra seguir a modinha? E, sendo honesto, tá melhor agora ou só trocamos um problema conhecido por um monte de problemas novos, mais chiques e bem mais caros, ignorando que monólitos bem feitos funcionam muito bem?"
Valeu por levantar essa bola! Assunto importante pra gente não cair em cilada só porque tá todo mundo falando e esquecer de olhar os exemplos que funcionam.