Essa frase te causa algum tipo de estranheza ou incômodo? Pois bem, foram essas as sensações que eu tive alguns dias atrás em uma live do canal Coding Night.
Eu explico, durante a nossa já tradicional Mesa Redonda, falamos sobre Docker e Kubernetes (caso queira conferir, clique aqui) e em um determinado momento, uma pessoa comenta que “Monolitos não escalam ou não escalam bem“, isso me deixou um pouco intrigado, de forma que cheguei a responder e tentar entender os motivos de tal afirmação, mas não obtive sucesso. Lembrando aqui que a minha intenção com esse post não é atacar ou rebater a pessoa, mas trazer essa reflexão à tona.
Escalabilidade?
Antes de chegarmos ao ponto central do post, é preciso deixar claro que existem duas formas de escalar uma aplicação (e sim, um monolito pode escalar das duas maneiras):
- Escalabilidade Vertical: Capacidade de aumentar os recursos (processador, memória, disco) de hardware de um único nó (máquina em utilização).
- Escalabilidade Horizontal: Capacidade de adicionar mais nós (aumentando a quantidade de máquinas provisionadas para rodar a aplicação de forma distribuída).
VERTICAL
HORIZONTAL


Pois bem, vamos aos fatos! Antes de mais nada, a simples afirmação que monolitos não escalam é uma falácia. Existem diversos motivos para sua aplicação não escalar, ser um monolito não é um deles. Além de já ter feito isso em vários clientes, você mesmo pode testar a escalabilidade da sua aplicação, principalmente se estiver usando algum serviço PaaS (Platform as a Service) para hospedá-la (como o Web App do Azure App Services, por exemplo) que lhe dá opções fáceis, rápidas e até automáticas para isso.
Mas ok, nem tudo são flores e eu preciso te falar que as vezes você não conseguirá ou terá dificuldades em escalar a sua aplicação e isso pode ser o que causa toda essa confusão, com a culpa recaindo sobre a arquitetura monolítica.
Monolitos escalam, o que não escala é um código mal implementado!
Essa afirmação pode parecer forte, mas sim, esse é um dos principais fatores para os problemas com escalabilidade. Para você que ainda acha que a culpa é da arquitetura em si, basta utilizar os mesmos códigos do seu monolito em uma arquitetura distribuída e verá que seus problemas de escalabilidade permanecerão!
Mas como assim um código mal implementado?
O fato é que um código ruim, mal implementado ou como queira chamar, sempre vai ter problemas, não só de escalabilidade, mas também de integração, performance, entre outros (mas esse vai ser um papo para outro post). Algumas práticas que podem ser utilizadas em uma aplicação que terá apenas uma instância rodando, não são válidas para uma que terá várias, por exemplo:
- Gravação e leitura de arquivos na máquina local: Alguma rotina que lê ou persiste dados em arquivos (que serão utilizados em um segundo momento);
- Manter o estado da aplicação em memória: Utilização de Sessions e variáveis estáticas, por exemplo.
Essas e outras práticas devem ser substituídas por abordagens distribuídas, uma vez que quando escalamos nossa aplicação de forma horizontal (como dito anteriormente), estamos provisionando mais máquinas para trabalhar paralelamente nas requisições que a aplicação recebe. Dessa forma cada um desses novos hardwares precisa ter acesso a esses recursos de forma independente.
Existem outros fatores que podem contribuir para que você não tenha o ganho esperado quando escala sua aplicação (achando que ele não está escalando). Aqui estão os dois que eu costumo ver com frequência:
- Gargalos em serviços de terceiros (uma API, por exemplo) que é chamada no meio do fluxo de alguma rotina;
- Banco de dados sobrecarregado por leitura e/ou gravação (A aplicação escalou, mas o banco não).
Fugindo um pouco do foco, vale a pena ressaltar a vantagem que as aplicações mais distribuídas (não necessariamente com microsserviços) tem em relação a escalabilidade, não do ponto de vista da possibilidade de escalar, mas da liberdade de escalar apenas o que é necessário, uma vez que os serviços são hospedados de forma independente.
Cuidado com o Hype!
Após esse evento, fiquei lembrando de muitos comentários semelhantes em torno desse assunto e tentando encontrar um motivo para a “demonização” dos monolitos e a idealização de microsserviços como a arquitetura perfeita para todas as aplicações (pelo menos é isso que tenho visto, inclusive em muitos posts espalhados pela internet). Isso simplesmente não faz sentido!
Lembrando, não há nenhum problema em você utilizar microsserviços, mas você deve implementar pelos motivos certos (que fazem sentido para o SEU negócio), NUNCA pelo hype e muito menos por falácias ou desculpas tendenciosas.
No momento de assumir as responsabilidades de uma escolha equivocada, o hype vai embora, mas você fica para resolver!
Ainda sobre monolitos e microsserviços, recomendo a leitura do post MonolithFirst do Martin Fowler e também o post Sobre Fórmula 1 e Microsserviços do meu amigo Luiz Carlos Faria.
Em breve, pretendo trazer mais conteúdos desse tipo, inclusive apontando soluções para alguns dos problemas que mencionei aqui.
Pra finalizar, saiba que planejar e principalmente implementar uma arquitetura baseada em microsserviços não é nem de longe uma tarefa fácil ou trivial! Levando em consideração a reflexão sobre o aspecto de escalabilidade, será que todos que não utilizam microsserviços estão fadados a ter problemas de escalabilidade? Se você tem isso em mente, esqueça! Alguém te vendeu um conceito errado!
Baseado nos feedbacks, também produzi um vídeo sobre o conteúdo do post. Sinta-se a vontade para compartilhar com seus amigos e deixar sua opinião nos comentários.
Valeu!
Gostei do texto, na hora de desenvolver a arquitetura do sistema devemos sempre verificar se é o caso de usar microserviços ou não.
Qual é a melhor solução para substituir a utilização do Session?
Olá Thiago, tudo bem?
Então, depende muito do que você está armazenando nessas Sessions.
Dando dois exemplos aqui:
* Se estiver usando elas para guardar informações referentes ao login do usuário, você pode muito bem utilizar cookies.
* Caso esteja armazenando algum objeto maior ou mais complexo que tenha que existir de forma temporária, você pode fazer uso de cache, sendo que existem várias alternativas para trabalhar com isso, uma delas é o Redis.
Valeu!