Microsserviços: conceitos iniciais
Um dos mais renomados líderes do Império Romano, Júlio César, uma vez disse que devemos "Dividir para conquistar", buscando ensinar a seus discípulos que ao encontrar um problema maior, se deve dividí-lo em pedaços menores e lidar um a um, simplificando assim sua solução. Ainda que centenas de anos à frente de seu tempo, sua frase continua a ser utilizável no conceito tecnológico quando surge na arquitetura de software um conceito chamado de microsserviços, que busca transformar uma aplicação única em diversos pedaços e conectá-los, simplificando assim seu entendimento e processamento.
Tipos de aplicações
Ao explorar a divisão de serviços tecnológicos, é crucial compreender os dois principais tipos predominantes nessa área:
Aplicações monolíticas
A aplicação monolítica, conhecida por sua simplicidade e eficiência em testes, é ideal para pequenos ou projetos iniciais, que ainda não demandam muitas funcionalidades ou endpoints para serem consumidos.
No entanto, quando se trata de escalabilidade, esse tipo de aplicação apresenta limitações. Seu longo tempo de deploy, restrições à diversidade tecnológica, dificultando a utilização de diferentes linguagens e frameworks, e suas falhas que podem derrubar todo o serviço tornam-se mais evidentes à medida que o projeto cresce. Esses desafios indicam que pode ser o momento de considerar a transição para uma arquitetura dividida entre vários pequenos serviços.
Microsserviços
Os microsserviços, diferentemente do tipo acima, representam uma abordagem mais moderna que divide a aplicação em pequenos serviços independentes, cada um comunicando-se através de APIs bem definidas. Essa arquitetura permite que equipes menores e autossuficientes trabalhem em projetos independentes, utilizando tecnologias específicas. Assim, falhas em um microsserviço não afetam o sistema inteiro, e os deploys são mais rápidos e frequentes.
Apesar de suas vantagens, os microsserviços também apresentam desafios. A complexidade aumenta resultando em preços mais altos e debugging mais complicado, além de necessitar de uma comunicação entre eles cuidadosamente planejada e com monitoramento mais complexo para garantir a integridade do sistema.
Criação de microsserviços
Quando começar?
Tendo em vista a diferença entre os principais sistemas e o ponto forte de cada um, fica a dúvida, qual escolher e por onde começar?
Em primeira análise, a recomendação inicial para a criação de projetos é seguir uma abordagem Monolith First, a qual opta por uma abordagem monolítica em primeira instância, devido a sua simplicidade e ao não conhecimento total das features que serão adicionadas e seu consumo de recursos. Conforme o projeto evolui e determinadas partes se tornam mais complexas, a prática é separá-las em microsserviços individuais e ir migrando gradualmente toda a aplicação para a arquitetura distribuida.
Com isso em mente e a aplicação bem estruturada, quando começarem as migrações é nescessário definir qual será o tipo que cada serviço ira ser para fornecer corretamente os dados para a aplicação. Existem diferentes tipos de microsserviços, cada um com sua função específica.
Abordagens de microsserviços
No cenário atual de desenvolvimento de software, uma abordagem que ganha destaque é o Domain Driven Design (DDD), que preconiza a modelagem do software com base no seu domínio específico. Em outras palavras, ao invés de focar apenas na persistência de dados, o DDD prioriza a compreensão e representação das regras de negócio e do contexto em que o software será utilizado. Neste contexto, a construção dos serviços é orientada pelo contrato, visando atender às necessidades específicas do projeto.
Dentro dessa perspectiva, os Serviços de Negócio desempenham um papel crucial. Eles são responsáveis por realizar operações que transcendem os limites de um único domínio, englobando funcionalidades de processos mais amplos. Um exemplo clássico é a matrícula de um aluno, que pode envolver diversos domínios, como o acadêmico, o financeiro e o administrativo. Esses serviços permitem encapsular esses domínios complexos, simplificando a interação com o cliente e facilitando o desenvolvimento de aplicações mais robustas e flexíveis.
Em situações mais complexas, onde múltiplos serviços de negócio precisam ser coordenados, entra em cena o conceito de Agregador de Processos. Este é um conjunto de serviços que se encarrega de orquestrar as interações entre os diferentes serviços necessários para a execução de um determinado processo. Embora menos comum, o Agregador de Processos é extremamente útil em cenários onde a complexidade é alta. Ele funciona como um padrão que faz chamadas para os serviços necessários e monta a resposta correta, podendo também incluir lógica de processamento adicional para garantir a integridade e eficiência das operações realizadas.
Como migrar de monolitos para multi-serviços?
Quando se trata de migrar de uma arquitetura monolítica para uma arquitetura distribuída, existem várias estratégias que podem ser empregadas para facilitar esse processo. Duas abordagens comuns são o Strangler Pattern e o Sidecar Pattern.
Strangler Pattern: Uma Abordagem Gradual
O Strangler Pattern é uma estratégia que envolve a quebra gradual das funcionalidades de um monolito em diversos microsserviços. Isso é feito isolando funcionalidades específicas ou domínios e transformando-os em serviços independentes. Ao longo do tempo, mais e mais funcionalidades são migradas para microsserviços, até que o monolito original seja "estrangulado" e substituído por uma arquitetura completamente distribuída. Essa abordagem permite uma migração gradual e controlada, reduzindo o risco de interrupções significativas no sistema.
Sidecar Pattern: Compartilhando Funcionalidades Comuns
O Sidecar Pattern é uma técnica que visa compartilhar pedaços de código comuns entre diversas aplicações, eliminando a necessidade de criar novos serviços para funcionalidades como login, por exemplo. Em termos mais técnicos, isso envolve a construção de um módulo compartilhado, como um pacote Node, Gradle ou Maven, que pode ser utilizado por diferentes serviços. Essa abordagem padroniza o código em todas as aplicações, promovendo a reutilização e simplificando o processo de desenvolvimento e manutenção.
Ambas as estratégias oferecem maneiras eficazes de migrar de uma arquitetura monolítica para uma arquitetura distribuída, permitindo uma transição suave e controlada para sistemas mais flexíveis e escaláveis. A escolha entre essas abordagens depende das necessidades específicas do projeto e das características do sistema existente.
Integração de Microsserviços: Estratégias e Considerações
Quando se trata de integrar microsserviços em um sistema, é fundamental considerar diversas estratégias e aspectos para garantir uma integração eficiente e sem complicações. Duas abordagens comuns são o uso de API Gateway e a definição clara de contratos entre os microsserviços.
API Gateway
O API Gateway desempenha um papel crucial na integração de microsserviços, fornecendo um ponto de entrada único para os clientes acessarem os diferentes serviços. Isso evita o caos na hora de fazer requisições, pois o gateway redireciona as solicitações para os serviços correspondentes e adapta o formato das requisições conforme necessário. Apesar das vantagens de simplificação e padronização para o cliente, o API Gateway pode se tornar um ponto único de falha e exigir um maior custo e tempo de desenvolvimento.
Em seu papel principal, ele realiza diversas funções como autorização, redirecionamento de requisições, modificação de decoradores no request, e a adequação aos formatos desejados pelo servidor e controle de acesso e dados .
Com exemplo, temos um tipo específico de gateway que é o Edge Pattern, onde os Edge services atuam como "Gateway de Ponta" direcionados para necessidades específicas de determinados clientes. Essa abordagem permite ajustes personalizados na frente do gateway para adaptá-lo a diferentes clientes.
Contrato entre Microsserviços
No mundo de requisições que funciona a internet atual, é crucial estabelecer "contratos" claros entre os microsserviços e os clientes, pois qualquer alteração nos endpoints existentes pode quebrar as aplicações que dependem deles. Para evitar isso, é recomendado fazer apenas modificações aditivas, como adicionar novos endpoints ou parâmetros opcionais. Entretando, é notório que uma hora a mudança total no serviço pode ser necessária, e para que isso ocorra sem muitas falahas o versionamento da API pode ser essencial.
Além disso, identificar os limites entre os microsserviços é fundamental para garantir uma arquitetura distribuída coesa. O Strangler Pattern e o DDD podem ajudar nesse processo. No entanto, é importante evitar a transformação excessiva de cada "substantivo" em microsserviço, pois isso pode levar à complexidade desnecessária e à necessidade de reagrupamento dos serviços posteriormente.
Estratégias para Lidar com Dados
Ao lidar com dados em arquiteturas de microsserviços, uma das considerações fundamentais é decidir se cada serviço terá seu próprio banco de dados ou se compartilharão um banco de dados central. Cada abordagem tem suas vantagens e desvantagens distintas.
Single Service Database: Banco de Dados por Serviço
Nesta abordagem, cada serviço possui seu próprio banco de dados, o que elimina a dependência entre os serviços e os bancos de dados. Isso permite uma maior independência e flexibilidade entre os serviços.
Desvantagens:
Vantagens:
Shared Service Database: Banco de Dados Compartilhado
Nesta abordagem, vários serviços compartilham um único banco de dados central. Isso geralmente ocorre devido a necessidades contratuais ou de dados comuns entre os serviços.
Esta abordagem oferece uma visão única e centralizada dos dados, facilitando a integração e a consistência entre os serviços.
No entanto, pode levar a problemas de acoplamento entre os serviços e pode aumentar a complexidade de gerenciamento do banco de dados.
Além disso, vale ressaltar que a junção dos dois serviços também pode ser válida, tudo depende de como você deseja arquitetar seu software para buscar um melhor rendimento.
Recomendados pelo LinkedIn
Gerenciamento de Hosts
Ao lidar com microsserviços, surge a questão de como gerenciar toda a arquitetura de desenvolvimento do projeto, especialmente quando se trata de incluir diversos servidores. Para superar esse desafio, é essencial planejar cuidadosamente onde o sistema será mantido, visando facilitar tanto o desenvolvimento quanto o processo de deploy. Abaixo tem-se algumas opções possíveis
Máquinas Virtuais
Uma opção é utilizar máquinas virtuais, onde é possível provisionar e adicionar várias máquinas virtuais ao computador. No entanto, em aplicações de microsserviços, executar várias máquinas em um único computador pode ser custoso em termos de processamento e memória, dificultando a execução de outras tarefas no mesmo sistema.
Desvantagens:
- Custoso em termos de processamento e memória, especialmente em aplicações de microsserviços.
Vantagens:
- Mais simples de trabalhar e configurar em aplicações monolíticas.
Nuvem (Cloud)
Muitos serviços de nuvem oferecem uma variedade de ferramentas necessárias para o desenvolvimento de aplicações sem a necessidade de gerenciar servidores próprios. No entanto, para protótipos locais e produção, contratar um servidor de nuvem pode ser caro e não trazer um retorno suficiente para o investimento.
Desvantagens:
- Custos elevados para protótipos locais e produção.
Contêineres
Atualmente, o uso de contêineres é altamente recomendado. Um ambiente de desenvolvimento baseado em contêineres pode ser facilmente criado e diversos serviços de nuvem oferecem a criação de servidores a partir de contêineres na produção.
Esta abordagem oferece uma excelente flexibilidade e eficiência, permitindo que os desenvolvedores trabalhem em um ambiente consistente e isolado, independentemente do sistema operacional do host, tornando-se a opção mais viável para a fase de desenvolvimento de seu projeto.
Tipos de Comunicação
Backend for Frontend (BFFs):
Os BFFs atuam como intermediários entre os clientes e os microsserviços, agregando e adaptando as solicitações do cliente antes de encaminhá-las aos serviços correspondentes. Isso ajuda a simplificar a lógica do cliente e isolar os microsserviços da complexidade da interação direta com diferentes tipos de clientes.
Comunicação Síncrona:
Na comunicação síncrona, as solicitações são tratadas de forma direta e imediata pelos microsserviços, que aguardam a conclusão da operação antes de retornar uma resposta ao cliente. Isso é comumente realizado por meio de chamadas de API RESTful utilizando o protocolo HTTP ou com gRPC, um protocolo de comunicação de alto desempenho.
Comunicação Assíncrona:
A comunicação assíncrona ocorre quando a resposta não é obtida imediatamente após a solicitação. Em vez disso, o cliente é notificado posteriormente, muitas vezes por meio de eventos ou mensagens assíncronas. Isso é frequentemente usado em cenários onde a resposta pode levar mais tempo, como processamento de background ou fluxos de eventos.
Lidando com Falhas
As estratégias para lidar com falhas incluem o uso de circuit breakers para interromper solicitações para serviços que estão indisponíveis ou com falha, o uso de cache para armazenar resultados de operações frequentes e reduzir a carga nos microsserviços, e o uso de retries com back-off para tentativas subsequentes de solicitações após uma falha, com intervalos crescentes entre as tentativas para evitar sobrecarregar os serviços.
Descoberta de Serviços
Para facilitar a descoberta de serviços, os microsserviços podem registrar-se em um serviço de descoberta ou um registro de serviço, como um servidor DNS especializado. Isso permite que outros serviços consultem o registro para localizar e se comunicar com os microsserviços necessários, mesmo em ambientes dinâmicos onde os endereços IP dos serviços podem mudar.
Essas abordagens proporcionam uma base sólida para uma comunicação eficiente e confiável entre os microsserviços, garantindo que a arquitetura distribuída seja resiliente e capaz de lidar com falhas e mudanças na escala de maneira eficaz.
Segurança
TODO sistema está aberto a ataques. A segurança não tenta limitar eles, mas sim dificulta-los, até porque seria impossivel uma aplicação 100% segura
A segurança é um aspecto crítico em qualquer aplicação web, especialmente em ambientes distribuídos como microsserviços. Vamos explorar como abordar a segurança em diferentes áreas-chave.
Transporte de Dados
O transporte seguro de dados é essencial para proteger a integridade e a confidencialidade das informações transmitidas pela rede. O HTTPS é amplamente utilizado para criptografar dados durante a transmissão, garantindo uma comunicação segura entre clientes e servidores.
Armazenamento de Dados
Ao armazenar dados, é crucial implementar medidas de segurança adequadas, como criptografia de disco, criptografia de banco de dados e anonimização de dados para proteger as informações armazenadas contra acesso não autorizado.
Autenticação
A autenticação é o processo de verificar a identidade de um usuário ou serviço. Existem várias técnicas de autenticação disponíveis, incluindo autenticação básica HTTP, tokens como JWT (JSON Web Tokens), OAuth e OpenID Connect, cada uma com suas próprias vantagens e casos de uso específicos.
Autorização
Enquanto a autenticação verifica a identidade do usuário, a autorização determina as permissões concedidas a esse usuário. As técnicas comuns de autorização incluem listas de controle de acesso (ACL), controle de acesso baseado em funções (RBAC) e delegação de autorização "on behalf of", cada uma definindo políticas para controlar o acesso aos recursos da aplicação.
Segurança na Rede
A segurança na rede é crucial para proteger os microsserviços contra ameaças externas. O uso de redes virtuais pode isolar os microsserviços que não precisam se comunicar com aplicativos externos, enquanto firewalls podem filtrar e bloquear solicitações suspeitas de clientes externos, aumentando a segurança da aplicação.
Defense in Depth
Adaptando a frase muito utilizada para o mundo de QA,
Quem tem 2 tem 1, quem tem 1 não tem nenhum
O princípio de "Defense in Depth" enfatiza a importância de implementar várias camadas de defesa para proteger os sistemas contra ataques. Isso inclui não apenas medidas técnicas, como criptografia e firewalls, mas também práticas de segurança proativas, como testes de penetração regulares, monitoramento em tempo real, auditorias de sistemas e treinamento de equipe em segurança da informação.
Portanto, é possível concluir que à medida que avançamos na era da tecnologia, os microsserviços emergem como uma abordagem poderosa para o desenvolvimento de aplicações escaláveis e flexíveis. Este artigo explorou os conceitos fundamentais dos microsserviços, desde sua arquitetura até suas vantagens e desafios.
Ao adotar microsserviços, as organizações têm a oportunidade de modularizar suas aplicações, facilitar a manutenção, promover a inovação e melhorar a escalabilidade. No entanto, é crucial reconhecer os desafios associados, como a complexidade da comunicação entre serviços e a necessidade de implementar estratégias robustas de segurança.
Em última análise, os microsserviços representam uma evolução significativa no desenvolvimento de software, capacitando as organizações a responderem de forma ágil às demandas do mercado e proporcionarem experiências excepcionais aos usuários finais. Ao compreender os princípios e as práticas recomendadas dos microsserviços, as empresas podem embarcar em uma jornada de transformação digital com confiança e determinação, impulsionando o sucesso e a inovação em um mundo cada vez mais conectado.
Vale ressaltar que esse artigo tratou de microsserviços de maneira a demonstrar sua complixidade, mas não explorou a fundo todas as suas áreas. É fundamental que, caso deseje aprender mais, a busca por conhecimento externo é essencial