Olá, eu sou Stanislav Yablonskiy, desenvolvedor de servidor principal na Pixonic (MY.GAMES). Os microservices são uma abordagem para o desenvolvimento de software (principalmente desenvolvimento backend) onde a funcionalidade é dividida nos menores componentes possíveis, cada um dos quais opera de forma independente.Cada um desses componentes tem sua própria API. Os microservices são muito populares hoje em dia, mas seu uso introduz uma vantagem significativa em termos de rede, memória e CPU. Cada chamada transforma-se na necessidade de serializar, enviar e receber dados através da rede.Além disso, já não é possível usar transações clássicas de banco de dados, o que leva a transações distribuídas ou eventual consistência. As transações distribuídas são lentas e caras, enquanto a eventual consistência significa que os resultados das operações podem não aparecer imediatamente e os dados podem ser temporariamente inconsistentes. O uso de microservices força os desenvolvedores a escrever mais código em cada serviço individual devido às dificuldades de acessar a lógica já escrita de outros serviços.Às vezes, é difícil reutilizar o código existente, ou você pode nem mesmo saber que ele existe – já que outras pessoas podem estar trabalhando em um projeto diferente. Microsserviços’ Overheads Baixar Overhead A depuração torna-se muito mais difícil com microservices. Um depurador regular é quase inútil em tais condições, uma vez que você não pode depurar todos os serviços de uma só vez. Sem um sistema de logging, rastreamento e métricas devidamente configurado, a depuração é quase impossível até que o problema seja localizado. Isso significa que você precisa de um ambiente especial onde não apenas o serviço que está sendo depurado esteja em execução, mas também todas as suas dependências (outros serviços, bancos de dados, filas, etc.). HTTP acima de tudo O protocolo HTTP tem muitas funcionalidades embutidas. suporta vários roteamentos, métodos de passagem de parâmetros, códigos de resposta e é suportado por muitos serviços prontos para uso (incluindo proxies). Protobuf acima da cabeça Serialização para comunicação de rede e deserialização ao receber mensagens são necessárias. Ao usar protobuf para troca de mensagens, você precisa: criação de objetos, transformá-los em águas alteradas, Despeje-os imediatamente após o uso. Isso cria muito trabalho extra para o coletor de lixo ou o gerente de memória dinâmica. Rede Overhead A transmissão de dados através da rede aumenta o tempo de resposta do serviço e aumenta o consumo de memória e CPU, mesmo que os microservices estejam sendo executados no mesmo host. Memória Overhead Enviar e receber mensagens requer a manutenção de estruturas de dados adicionais, usando fios separados e sincronizando-os.Cada processo separado, especialmente um executado em um contêiner, consome uma quantidade significativa de memória apenas por existência. CPU acima de tudo Naturalmente, toda esta comunicação entre processos e entre contêineres requer recursos de computação. Base de dados Overhead As transações normais são impossíveis quando as operações se estendem a múltiplos microsserviços.As transações distribuídas são muito mais lentas e exigem coordenação complexa – muitas vezes manual. Discos de Rede Overhead Os contêineres de microsserviços são frequentemente executados em discos montados em rede, o que aumenta a latência, reduz o desempenho (IOPS) e torna imprevisível. Projeto Borders Overhead A concepção e o desenvolvimento de microsserviços traz dificuldades na evolução e refactoring de um projeto. Não é fácil mudar a área de responsabilidade de um serviço. Você não pode simplesmente mover código de um serviço para outro. Isso geralmente requer: muito tempo e esforço, Várias versões de API, e migrações complexas antes que a funcionalidade possa ser redistribuída entre os serviços. Além disso, se você quiser atualizar ou substituir uma biblioteca, você precisará fazê-lo em todos os projetos, não apenas um. Infraestrutura acima de tudo Você não pode simplesmente “fazer microsserviços”.Você precisará de infraestrutura – não, INFRASTRUCTURA: contêineres (cada um contendo cópias de bibliotecas compartilhadas), Os cubos, Serviços em nuvem, As raízes (RabbitMQ e Kafka) ferramentas de sincronização de configuração (Zookeeper, Etcd, Consul), e assim por diante. Tudo isso exige enormes recursos tanto de máquinas quanto de pessoas. Deslocamento Independente Overhead Apoiar implantações independentes significa: Cada serviço deve ser implantável separadamente, Cada um deve ter seu próprio tubo CI/CD, E a parte mais difícil - a versão de API. Cada serviço terá que suportar várias versões da API simultaneamente e os chamadores terão que rastrear essas versões e atualizar suas chamadas a tempo. Bolas de lama distribuídas Em vez de microsserviços limpos, você acabará com uma bola de lama distribuída – onde a funcionalidade é mal distribuída, chamadas externas desencadeiam cadeias inteiras de chamadas de serviço interno e a coisa toda é terrívelmente lenta. O monólito é realmente tão assustador? Monolítico Modular Os monólitos modulares permitem que você evite a maior parte do overhead de microsserviços - enquanto ainda fornece separação que pode ser usada mais tarde, se necessário. Esta abordagem envolve escrever o aplicativo (principalmente o backend) como um único serviço dividido em módulos individuais com: limites claramente definidos, e interdependência mínima. Isso torna possível dividi-los em serviços se a escalação realmente o exigir. Espere, você pode fazer isso? Muitos benefícios atribuídos à arquitetura de microsserviços podem ser alcançados em um monólito: A modularidade pode ser implementada com recursos de linguagem: classes, nomes, projetos e assembleias; Multiplos bancos de dados – possível, se realmente necessário; Línguas múltiplas – também possível, por exemplo, combinar C/C++/C#/Java com linguagens de script como JavaScript, Python ou Erlang para desenvolvimento de nível superior; Interop – muitas plataformas suportam chamadas C/C++ a partir de Java, C#, Python, JavaScript ou Erlang; Corridas de mensagens – basta usar a estrutura de dados apropriada. E quando você quer depurar - uma tecla, e todo o aplicativo está ao seu alcance. Ator Frameworks O Actor Frameworks permite que você crie microservices – sem os microservices. Toda a lógica é dividida em classes (atores) que só se comunicam através de um bus de mensagens (queues). Esses atores podem: existem dentro de um único processo, ou distribuídos em vários processos. Desta forma, você obtém o modelo de programação de microsserviços, mas a maior parte da infraestrutura é gerenciada pelo próprio framework. Conclusion CONCLUSÃO A arquitetura deve ser escolhida com base em: Requisitos do projeto, os recursos disponíveis, e experiência da equipe. Eles são úteis para grandes projetos e equipes – mas o monólito não é obsoleto e não é uma dívida técnica por padrão. O que mais importa é o equilíbrio entre flexibilidade e complexidade, escalabilidade e manutenção – para que o sistema que você constrói seja eficaz e sustentável.