Microsserviços Pragmáticos

Atualmente, microsserviços é uma das “palavras da moda” mais populares na área da arquitetura de software. Existe muito material de estudo sobre os fundamentos e os benefícios dos microsserviços, mas têm poucos recursos sobre como você pode usá-los nos cenários corporativos do mundo real.

Neste post, estou planejando abordar os principais conceitos da Arquitetura de Microsserviços (MSA) e como você pode usar esses princípios de arquitetura na prática.

Arquitetura Monolítica

As aplicações de software corporativas são projetadas para simplificar vários requisitos de negócio. Assim, uma determinada aplicação de software oferece centenas de funcionalidades e todas essas funcionalidades são empilhadas em uma única aplicação monolítica. Por exemplo, ERPs, CRMs e outros vários sistemas de software são construídos como um monólito com várias centenas de funcionalidades. A implantação, a solução de problemas, o dimensionamento e a escalabilidade desses enormes aplicativos de software é um pesadelo.

A Arquitetura Orientada a Serviços (SOA) foi projetada para superar algumas das limitações mencionadas, introduzindo o conceito de ‘serviço’, que é uma agregação e um agrupamento de funcionalidades similares oferecidas por uma aplicação. Portanto, com o SOA, uma aplicação de software é projetada como uma combinação de serviços de “granularidade grossa” (coarse-grained services). Entretanto, em SOA, o escopo do serviço é muito amplo. Isso conduz a serviços complexos e gigantescos com várias dezenas de operações (funcionalidades), juntamente com formatos e padrões de mensagens complexos (por exemplo: todos os padrões WS*).

Figura 1: Arquitetura Monolítica

Na maioria dos casos, os serviços em SOA são independentes uns dos outros, mas são implementados no mesmo ambiente de execução, juntamente com todos os outros serviços (pense em ter várias aplicações Web que são implementadas na mesma instância do Tomcat). Semelhante às aplicações de software monolíticas, esses serviços têm o hábito de crescer com o tempo, acumulando várias funcionalidades. Literalmente, isso transforma essas aplicações em componentes monolíticos que não são diferentes das aplicações monolíticas convencionais, como os ERPs. A Figura 1 mostra uma aplicação de software de varejo que compreende vários serviços. Todos esses serviços são implantados dentro do mesmo ambiente de execução da aplicação. Então, esse é um ótimo exemplo de arquitetura monolítica. Aqui estão algumas das características de tais aplicações que são baseadas na arquitetura monolítica.

  • As aplicações monolíticas são projetadas, desenvolvidas e implantadas como uma única unidade;

  • As aplicações monolíticas são incrivelmente complexas; o que leva a “pesadelos” na manutenção, na atualização e na adição de novos recursos;

  • É difícil utilizar as metodologias ágeis de desenvolvimento e entrega com uma arquitetura monolítica;

  • É necessário reimplantar a aplicação inteira para atualizar apenas uma parte dela;

  • Escalabilidade: tem que ser instanciada como uma única aplicação e é difícil de escalar com requisitos de recursos conflitantes (por exemplo: um serviço requer mais CPU enquanto o outro requer mais memória);

  • Confiabilidade: um serviço instável pode derrubar toda a aplicação;

  • Difícil de inovar: é realmente difícil adotar novas tecnologias e frameworks, já que todas as funcionalidades precisam ser construídas com base em tecnologias/frameworks homogêneos.

Essas características da Arquitetura Monolítica têm levado à Arquitetura de Microsserviços.

Arquitetura de Microsserviços

A base da arquitetura de microsserviços (MSA) está no desenvolvimento de uma única aplicação como um conjunto de serviços pequenos e independentes que executam em seu próprio processo, e são desenvolvidos e implantados (colocados em execução) de forma independente.

Na maioria das definições de arquitetura de microsserviços, ela é descrita como o processo de separar os serviços disponíveis no monólito em um conjunto de serviços independentes. No entanto, na minha opinião, essa arquitetura não se limita a dividir os serviços disponíveis no monólito em serviços independentes.

A ideia-chave é que, observando as funcionalidades oferecidas pelo monólito, podemos identificar os recursos de negócio que são necessários. Então, esses recursos de negócio podem ser implementados como serviços totalmente independentes, de granularidade fina (fine-grained) e autocontidos. Eles podem ser implementados utilizando diferentes tecnologias, com cada serviço abordando um escopo muito específico e limitado do negócio.

Portanto, o cenário do sistema de varejo on-line que citamos acima pode ser implementado utilizando a arquitetura de microsserviços, conforme representado na Figura 2. Com essa arquitetura, a aplicação de software de varejo é implementada como um conjunto de microsserviços. Assim, como você pode perceber nessa figura, com base nos requisitos do negócio, há um microsserviço adicional criado a partir do conjunto original de serviços que estão no monólito. Portanto, é bastante óbvio que usar a arquitetura de microsserviços é algo além da divisão dos serviços do monólito.

Figura 2: Arquitetura de Microsserviço

Então, vamos nos aprofundar nos princípios-chave da arquitetura de microsserviços e, mais importante, vamos nos concentrar em como eles podem ser usados ​​na prática.

Projetando microsserviços: tamanho, escopo e recursos

Você pode estar construindo seu aplicativo de software “do zero” usando a arquitetura de microsserviços ou convertendo aplicações/serviços existentes em microsserviços. Em qualquer destes casos, é muito importante que você decida adequadamente o tamanho, o escopo e os recursos dos microsserviços. Provavelmente, essa é a tarefa mais difícil que você encontrará inicialmente ao implementar a arquitetura de microsserviços na prática.

Vamos discutir algumas das principais questões práticas e equívocos relacionados ao tamanho, ao escopo e às funcionalidades dos microsserviços:

  • As linhas de código/tamanho da equipe são métricas ruins: há várias discussões sobre a decisão do tamanho dos microsserviços com base nas linhas de código de sua implementação ou no tamanho de sua equipe (isto é, “equipe de duas pizzas”). No entanto, essas métricas são consideradas muito ruins e impraticáveis porque ainda podemos desenvolver serviços com menos código/com tamanho de equipe de duas pizzas, mas violando totalmente os princípios de arquitetura de microsserviço;

  • Micro’ é um termo um pouco enganoso: a maioria dos desenvolvedores tende a pensar que eles deveriam tentar fazer um serviço que seja o menor possível. Esta é uma interpretação errônea;

  • No contexto de SOA, os serviços são frequentemente implementados como componentes monolíticos, com suporte para várias dezenas de operações/funcionalidades. Desta forma, ter serviços semelhantes a SOA e redefinindo estes serviços como microsserviços não lhe oferecerá nenhum dos benefícios da arquitetura de microsserviços.

Então, como devemos projetar os serviços adequadamente na Arquitetura de Microsserviços?

Diretrizes para Projetar Microsserviços

  • Princípio de Responsabilidade Única: Ter um escopo de negócio limitado e focado para cada microsserviço nos ajuda a conseguir a agilidade no desenvolvimento e na entrega dos serviços;

  • Durante a fase de projeto dos microsserviços, devemos encontrar seus limites e alinhá-los com as funcionalidades do negócio (isso é conhecido como Bounded Context no Domain-Driven-Design);

  • Certifique-se de que o projeto dos microsserviços garanta o desenvolvimento e a implementação ágil e independente do serviço;

  • Nosso foco deve estar no escopo do microsserviço, mas não em tornar o serviço menor. O tamanho (correto) do serviço deve ser o tamanho necessário para viabilizar uma determinada funcionalidade do negócio;

  • Ao contrário dos serviços em SOA, um determinado microsserviço deve ter pouquíssimas operações/funcionalidades e um formato de mensagem simples;

  • Geralmente é uma boa prática iniciar com limites de serviço relativamente amplos e refatorá-los para limites menores (com base nos requisitos do negócio) com o passar do tempo.

Em nosso caso de uso de varejo, você pode descobrir que dividimos as funcionalidades de seu monólito em quatro microsserviços diferentes, como ‘estoque’, ‘contabilidade’, ‘remessa’ e ‘armazenamento’. Eles estão endereçando um escopo de negócio limitado e focado, de modo que cada serviço seja totalmente desacoplado do outro e garanta a agilidade no desenvolvimento e na implantação.

Mensagens em microsserviços

Em aplicativos monolíticos, as funcionalidades de negócio de diferentes processadores/componentes são invocadas usando chamadas de função ou chamadas de método no nível da linguagem. Em SOA, isso foi transferido para um sistema de mensagens do nível de serviço Web muito mais fracamente acoplado, que é baseado principalmente no SOAP, usando diferentes protocolos, como HTTP e JMS. Os webservices com várias dezenas de operações e esquemas complexos de mensagens eram o principal fator impeditivo para a popularização do padrão webservice. Na arquitetura de microsserviços é necessário ter um mecanismo de mensagens simples e leve.

Mensagens Síncronas – REST, Thrift

Para mensagens síncronas (nas quais o cliente espera uma resposta do serviço em um tempo adequado e aguarda até obtê-la) na Arquitetura de Microsserviços, o REST é a escolha unânime, pois fornece um estilo de mensagens simples, implementado com HTTP request-response, no estilo de API baseada em recursos. Portanto, a maioria das implementações de microsserviços está usando HTTP junto com o estilo de APIs baseadas em recursos, onde cada funcionalidade é representada como um recurso com operações executadas sobre esses recursos.

Figura 3: Usando interfaces REST para expor microsserviços

O Thrift é usado (no qual você pode especificar uma definição de interface para o seu microsserviço) como uma alternativa ao sistema de mensagens síncronas REST/HTTP.

>>Leitura recomendada: Migração para microsserviços: como funciona?

Mensagens Assíncronas – AMQP, STOMP, MQTT

Para alguns cenários de microsserviços, é necessário usar técnicas de mensagens assíncronas (o cliente não espera uma resposta imediatamente ou não aceita uma resposta). Em tais cenários, os protocolos de mensagens assíncronas, como AMQP , STOMP ou MQTT, são amplamente utilizados.

Formatos de Mensagem – JSON, XML, Thrift, ProtoBuf, Avro

Decidir o formato de mensagem mais adequado para os microsserviços é outro fator chave. As aplicações monolíticas tradicionais usam formatos binários complexos, as aplicações baseadas em SOA/serviços da Web usam mensagens de texto com base nos formatos complexos de mensagem (SOAP) e esquemas (xsd). Na maioria das aplicações baseadas em microsserviços, os formatos de mensagens baseados em texto são simples, como JSON e XML usando o estilo de API baseada em recursos (tipicamente REST). Nos casos em que precisamos de formatos binários de mensagens (as mensagens de texto podem se tornar prolixas em alguns casos de uso), os microsserviços podem utilizar formatos binários de mensagens como Thrift binário, ProtoBuf ou Avro.

Contratos de Serviço: Definindo as interfaces de serviço – Swagger, RAML, Thrift IDL

Quando você tem um recurso de negócio implementado como um serviço, você precisa definir e publicar o contrato de serviço. Em aplicações monolíticas tradicionais, dificilmente encontramos essa funcionalidade para definir os recursos de negócio de uma aplicação. No mundo SOA/serviços da Web, o WSDL é usado para definir o contrato de serviço, mas como todos nós sabemos, o WSDL não é a solução ideal para definir contrato de microsserviços, pois o WSDL é incrivelmente complexo e fortemente acoplado ao SOAP.

Então, como construímos microsserviços com o estilo arquitetural REST, podemos usar as mesmas técnicas de definição da REST API para definir o contrato dos microsserviços. Desta forma, os microsserviços usam as linguagens de definição do padrão REST API, como Swagger e RAML, para definir os contratos de serviço.

Para outras implementações de microsserviço que não são baseadas em HTTP/REST, como o Thrift, podemos usar a Linguagem de Definição de Interface (IDL)  do nível de protocolo (por exemplo: Thrift IDL ).

>>Leitura recomendada: Microsserviços: propriedades, benefícios e aplicações

Integração de Microsserviços (comunicação entre serviços/processos)

Na arquitetura de Microsserviços, as aplicações de software são criadas como um conjunto de serviços independentes. Assim, para implementar um caso de uso de negócios, é necessário ter as estruturas de comunicação entre diferentes microsserviços/processos. É por isso que a comunicação “interserviços/processos” entre microsserviços é um aspecto tão vital.

Em implementações SOA, a comunicação entre serviços é viabilizada com um Enterprise Service Bus (ESB) e a maior parte da lógica do negócio reside na camada intermediária (roteamento de mensagens, transformação e orquestração). No entanto, a arquitetura de microsserviços promove a eliminação do barramento central de mensagens/ESB e move a inteligência ou lógica do negócio para os serviços e para os clientes (conhecidos como terminais inteligentes – ‘Smart Endpoints’).

Como os microsserviços usam protocolos padrão, como HTTP, JSON etc., o requisito de integração com protocolos diferentes é mínimo quando se trata da comunicação entre microsserviços. Outra abordagem alternativa na comunicação do Microsserviço é usar um barramento de mensagens leve ou gateway com o mínimo de recursos de roteamento e atuando apenas como um “fluxo simples” (dumb pipe) sem lógica do negócio implementada no gateway. Com base nesses estilos, existem vários patterns de comunicação que surgiram na arquitetura de microsserviços.

Estilo ponto-a-ponto – Invocando serviços diretamente

No estilo ponto-a-ponto, toda a lógica de roteamento de mensagens reside em cada terminal (endpoint) e os serviços podem se comunicar diretamente. Cada microsserviço expõe uma REST API e um determinado microsserviço ou um cliente externo pode invocar outro microsserviço através de sua REST API.

Figura 4: Comunicação entre serviços com conectividade ponto-a-ponto.

Obviamente, esse modelo funciona para aplicativos baseados em microsserviços relativamente simples, mas à medida que o número de serviços aumenta, isso se tornará incrivelmente complexo. Afinal de contas, essa é exatamente a mesma razão para se usar o ESB na implementação tradicional de SOA – livrar-se desses confusos links de integração ponto-a-ponto. Vamos tentar resumir as principais desvantagens do estilo ponto-a-ponto para a comunicação de microsserviço:

  • Os requisitos não funcionais, como autenticação do usuário final, throttling (limite de uso), monitoramento, etc., devem ser implementados em todos os níveis de microsserviço;

  • Como resultado da duplicação de funcionalidades comuns, cada implementação de microsserviço pode tornar-se complexa;

  • Não há nenhum tipo de controle sobre a comunicação entre os serviços e os clientes (mesmo para monitoramento, rastreamento ou filtragem);

  • Frequentemente, o estilo de comunicação direta é considerado como um anti-pattern de microsserviço para implementações de microsserviços em larga escala.

Assim sendo, para os casos de uso de microsserviços complexos, em vez de ter conectividade ponto-a-ponto ou ter um ESB central, poderíamos ter um barramento central de mensagens leve que pode fornecer uma camada de abstração para os microsserviços e que pode ser usado para implementar vários requisitos não-funcionais. Esse estilo é conhecido como estilo API Gateway.

Estilo API Gateway (API-GW)

A principal ideia por trás do estilo API Gateway é usar um gateway de mensagens leve como ponto de entrada principal para todos os clientes/consumidores e implementar os requisitos não-funcionais comuns no nível do gateway. Em geral, um API Gateway permite que você consuma uma API gerenciada usando REST/HTTP. Portanto, aqui podemos expor nossas funcionalidades de negócio que são implementadas como microsserviços, por meio da API-GW, como APIs gerenciadas. Na verdade, esta é uma combinação de arquitetura de microsserviços e API-Management, que oferece o melhor dos dois mundos.

Figura 5: Todos os microsserviços são expostos através de um API-GW.

Em nosso cenário de negócios de varejo, como mostrado na Figura 5, todos os microsserviços são expostos através de um API-GW e esse é o único ponto de entrada para todos os clientes. Se um microsserviço quiser consumir outro microsserviço isso também precisa ser feito através do API-GW.

O estilo API-GW oferece as seguintes vantagens:

  • Capacidade de fornecer as abstrações necessárias no nível do gateway para os microsserviçosPor exemplo, ao invés de fornecer uma API do estilo “tamanho único serve para todos”, o API Gateway pode expor uma API diferente para cada cliente;

  • Roteamento/transformações de mensagens leves no nível do gateway;

  • Local central para aplicar requisitos não-funcionais, como segurança, monitoramento e throttling;

  • Com o uso do padrão API-GW, o microsserviço se torna ainda mais leve, já que todos os requisitos não-funcionais são implementados no nível do Gateway.

O estilo API-GW poderia muito bem ser o pattern mais usado na maioria das implementações de microsserviço.

Estilo Message Broker

Os microsserviços podem ser integrados no cenário de mensagens assíncronas, tal como solicitações unidirecionais e mensagens de publicação e assinatura (publish-subscribe messaging) usando filas ou tópicos. Um determinado microsserviço pode ser o produtor da mensagem e pode enviar de forma assíncrona essa mensagem para uma fila ou tópico. Em seguida, o microsserviço consumidor pode consumir mensagens da fila ou do tópico. Esse estilo separa os produtores de mensagens dos consumidores e o message broker intermediário armazenará mensagens em buffer até que o consumidor possa processá-las. Os microsserviços do produtor desconhecem completamente os microsserviços do consumidor.

Figura 6: Integração baseada em mensagens assíncronas usando publish-subscribe.

A comunicação entre os consumidores/produtores é facilitada por meio de um message broker que é baseado em padrões de mensagens assíncronas, como AMQP, MQTT etc.

Gerenciamento de Dados Descentralizados

Na arquitetura monolítica, a aplicação armazena dados em um único banco de dados centralizado para implementar várias funcionalidades/recursos da aplicação.

Figura 7: A aplicação monolítica usa um banco de dados centralizado para implementar todas as suas funcionalidades.

Na arquitetura de microsserviços, as funcionalidades são distribuídas em vários microsserviços e, se usarmos o mesmo banco de dados centralizado, os microsserviços não serão mais independentes uns dos outros (por exemplo, se o esquema do banco de dados tiver mudado a partir de um determinado microsserviço, isso irá interromper vários outros serviços). Portanto, cada microsserviço precisa ter seu próprio banco de dados.

Figura 8: Os microsserviços possuem seu próprio banco de dados privado e não podem acessar diretamente o banco de dados de outros microsserviços.

Aqui está o aspecto chave da implementação do gerenciamento descentralizado de dados na arquitetura de microsserviços:

  • Cada microsserviço pode ter um banco de dados privado para persistir os dados necessários para implementar a funcionalidade de negócio oferecida a partir dele;

  • Um determinado microsserviço só pode acessar o banco de dados privado dedicado, mas não os bancos de dados de outros microsserviços;

  • Em alguns cenários de negócio, talvez seja necessário atualizar vários bancos de dados para uma única transação. Em tais cenários, os bancos de dados de outros microsserviços devem ser atualizados apenas por meio de sua API de serviço (não é permitido acessar diretamente o banco de dados).

O gerenciamento de dados descentralizados oferece microsserviços totalmente desacoplados e a liberdade de escolher técnicas de gerenciamento de dados distintas (SQL ou NoSQL etc., sistemas de gerenciamento de banco de dados diferentes para cada serviço). No entanto, para casos de uso transacionais complexos que envolvem vários microsserviços, o comportamento transacional deve ser implementado usando as APIs oferecidas por cada serviço e a lógica reside no nível do cliente ou no nível intermediário (GW).

Governança Descentralizada

A arquitetura de microsserviços favorece a governança descentralizada.

Em geral, ‘governança’ significa estabelecer e impor o modo como as pessoas e as soluções trabalham juntas para atingir os objetivos organizacionais. No contexto de SOA, a governança SOA orienta o desenvolvimento de serviços reutilizáveis, estabelecendo como os serviços serão projetados e desenvolvidos e como esses serviços serão alterados ao longo do tempo. Também estabelece acordos entre os provedores de serviços e os consumidores desses serviços, dizendo aos consumidores o que eles podem esperar e aos fornecedores o que eles são obrigados a fornecer. Existem dois tipos comuns de governança em SOA:

  • Governança em tempo de projeto (Design-time governance) – definir e controlar as criações de serviço, o projeto e a implementação de políticas de serviço.

  • Governança em tempo de execução (Run-time governance) – a capacidade de impor políticas de serviço durante a execução.

Então, o que a governança no contexto de microsserviços realmente significa? Na arquitetura de microsserviços, estes são construídos como serviços totalmente independentes e desacoplados, com uma variedade de tecnologias e plataformas. Portanto, não há necessidade de definir padrões comuns para o projeto e desenvolvimento de serviços. Assim, podemos resumir as funcionalidades de governança descentralizada dos microsserviços da seguinte forma:

  • Na arquitetura de microsserviços, não é necessário ter uma governança em tempo de projeto centralizada;

  • Os microsserviços podem tomar suas próprias decisões sobre seu projeto e sua implementação;

  • A arquitetura de microsserviços promove o compartilhamento de serviços comuns/reutilizáveis;

  • Alguns dos aspectos de governança em tempo de execução, como SLAs, throttling, monitoramento, requisitos de segurança comuns e descoberta de serviço podem ser implementados no nível do API-GW.

Registro de Serviço e Descoberta de Serviço

Na arquitetura de microsserviços, o número de microsserviços com os quais você precisa lidar é bastante alto. E também suas localizações mudam dinamicamente devido à natureza rápida e ágil do desenvolvimento/implantação de microsserviços. Assim sendo, você precisa encontrar a localização de um microsserviço durante o tempo de execução e a solução para esse problema é usar um registro de serviço (Service Registry).

Registro de Serviço

O registro de serviço mantém as instâncias de microsserviços e suas localizações. As instâncias do microsserviço são registradas com o registro de serviço na sua inicialização e são canceladas no seu desligamento. Os consumidores podem encontrar os microsserviços disponíveis e suas localizações através do registro de serviços.

Descoberta de Serviço

Para encontrar os microsserviços disponíveis e sua localização, precisamos ter um mecanismo de descoberta de serviço. Existem dois tipos de mecanismos de descoberta de serviço: Descoberta do lado do cliente e Descoberta do lado do servidor. Vamos dar uma olhada mais de perto nesses dois mecanismos de descoberta de serviço.

Descoberta do lado do cliente

Nessa abordagem, o cliente ou o API-GW obtém a localização de uma instância de um serviço consultando um registro de serviço (Service Registry).

Figura 9 – Descoberta do lado do cliente

Aqui, o cliente/API-GW precisa implementar a lógica de descoberta de serviço chamando o componente Service-Registry.

Descoberta do lado do servidor

Nessa abordagem, os clientes/API-GW enviam a solicitação para um componente (como um balanceador de carga) que é executado em uma localização conhecida. Esse componente chama o registro de serviço e determina a localização absoluta do microsserviço.

Figura 10 – Descoberta do lado do servidor

As soluções de implantação de microsserviços, como o Kubernetes, oferecem mecanismos de descoberta do lado do serviço.

Implantação

Quando se trata da arquitetura de microsserviços, a implantação dos microsserviços desempenha um papel fundamental e tem os seguintes requisitos principais:

  • Capacidade de implantar/remover um microsserviço, independentemente dos demais;

  • Deve ser capaz de escalar em cada nível de microsserviço (um determinado serviço pode obter mais tráfego do que outros serviços);

  • Construir e implantar microsserviços;

  • Falha em um microsserviço não deve afetar nenhum dos outros serviços.

O Docker (um mecanismo de software livre que permite que desenvolvedores e administradores de sistemas implantem contêineres de aplicações autossuficientes em ambientes Linux) fornece uma ótima maneira de implantar microsserviços que atendem aos requisitos acima. Os principais passos envolvidos são os seguintes:

  • Empacotar o microsserviço como uma imagem de contêiner (Docker);

  • Implementar cada instância do serviço como um contêiner;

  • A escalabilidade é feita com base na alteração do número de instâncias de contêiner;

  • A construção, a implantação e a inicialização do microsserviço serão muito mais rápidas, já que estamos usando contêineres do Docker (que é muito mais rápido do que uma máquina virtual comum).

O Kubernetes estende os recursos do Docker, pois permite gerenciar um cluster de contêineres Linux como um sistema único, gerencia e executa contêineres Docker em vários hosts, oferece colocação de contêineres, descoberta de serviço e controle de replicação. Como você pode ver, a maioria desses recursos também é essencial em nosso contexto de microsserviços. Portanto, usar o Kubernetes (com o Docker) para implantação de microsserviços tornou-se uma abordagem extremamente poderosa, especialmente para implantações de microsserviços em larga escala.

Figura 11: Construindo e implantando microsserviços como contêineres.

A Figura 11, apresenta uma visão geral da implantação dos microsserviços da aplicação de varejo. Cada instância do microsserviço é implantada como um contêiner e há dois contêineres para cada host.

Segurança

A segurança dos microsserviços é um requisito bastante comum quando você usa microsserviços em cenários do mundo real. Antes de entrar na segurança dos microsserviços, vamos dar uma rápida olhada em como normalmente implementamos a segurança no nível de aplicações monolíticas.

  • Em uma típica aplicação monolítica, a segurança está em descobrir “quem é o chamador”, “o que o chamador pode fazer” e “como propagamos essa informação”;

  • Isso geralmente é implementado em um componente de segurança comum que está no início da cadeia de tratamento de solicitações e esse componente preenche as informações necessárias com o uso de um repositório de usuários subjacente.

Então, podemos traduzir diretamente esse pattern para a arquitetura de microsserviços? Sim, mas isso requer um componente de segurança implementado em cada nível de microsserviços que conversa com um repositório de usuários centralizado/compartilhado e recupera as informações necessárias. Essa é uma abordagem muito tediosa para resolver o problema de segurança dos microsserviços.

Em vez disso, podemos aproveitar os padrões amplamente usados ​​de API-Security, como OAuth2 e OpenID Connect, para encontrar uma solução melhor para o problema de segurança dos microsserviços. Antes de aprofundar nessa questão, deixe-me resumir o propósito de cada padrão e como podemos usá-los:

  • OAuth2 – é um protocolo de delegação de acesso. O cliente autentica com o servidor de autorização e obtém um token opaco que é conhecido como ‘token de acesso’. O token de acesso não tem nenhuma informação sobre o usuário/cliente. Ele tem apenas uma referência às informações do usuário que só podem ser recuperadas pelo servidor de autorização. Portanto, isso é conhecido como um ‘token por referência’ (by-reference token) e é seguro usar esse token mesmo na rede pública/internet;

  • O OpenID Connect comporta-se de maneira semelhante ao OAuth, mas, além do token de acesso, o servidor de autorização emite um token de ID que contém informações sobre o usuário. Isso geralmente é implementado por um JWT (JSON Web Token) e é assinado pelo servidor de autorização. Portanto, isso garante a confiabilidade entre o servidor de autorização e o cliente. O token JWT é, portanto, conhecido como um ‘token por valor’ (by-value token), pois contém as informações do usuário e, obviamente, não é seguro usá-lo fora da rede interna.

Agora, vamos ver como podemos usar esses padrões para proteger microsserviços em nosso exemplo de varejo.

Figura 12: Segurança de microsserviço com OAuth2 e OpenID Connect

Como mostrado na Figura 12, estas são as principais etapas envolvidas na implementação da segurança de microsserviços:

  • Deixe a autenticação para o OAuth e para o servidor OpenID Connect (servidor de autorização), para que os microsserviços possam fornecer acesso para aqueles que tem o direito de usar os dados;

  • Use o estilo API-GW, no qual existe um único ponto de entrada para todas as solicitações do cliente;

  • O cliente se conecta ao servidor de autorização e obtém o token de acesso (token por referência). Em seguida, envia o token de acesso à API-GW juntamente com a solicitação;

  • Tradução de token no gateway – o API-GW extrai o token de acesso e o envia ao servidor de autorização para recuperar o JWT (token por valor);

  • Então, o GW passa esse JWT junto com a solicitação para a camada de microsserviços;

  • Os JWTs contêm as informações necessárias para ajudar no armazenamento de sessões de usuários, etc. Se cada serviço puder entender um JSON Web Token, então você terá distribuído seu mecanismo de identificação, que permite transportar a identificação através de todo o sistema;

  • Em cada camada de microsserviço, podemos ter um componente que processa o JWT, que é uma implementação bastante simples.

Transações

E quanto ao suporte a transações em microsserviços? Na verdade, dar suporte às transações distribuídas em vários microsserviços é uma tarefa excepcionalmente complexa. A arquitetura de microsserviço em si incentiva a coordenação sem transações entre os serviços.

A ideia é que um determinado serviço seja totalmente autocontido e baseado no princípio da responsabilidade única. A necessidade de ter transações distribuídas através de múltiplos microsserviços é normalmente um sintoma de falha de projeto na arquitetura de microsserviço e geralmente pode ser resolvida refatorando os escopos dos microsserviços.

No entanto, se houver um requisito obrigatório para ter transações distribuídas através de múltiplos serviços, então esses cenários podem ser implementados com a introdução de ‘operações de compensação’ em cada nível de microsserviço. A ideia-chave desse conceito é que um determinado microsserviço é baseado no princípio da responsabilidade única e, se um dado microsserviço falhou ao executar uma determinada operação, podemos considerar isso como uma falha desse microsserviço em sua totalidade. Então, todas as outras operações já realizadas devem ser desfeitas invocando a respectiva operação de compensação desses microsserviços.

Projeto para falhas

A arquitetura de microsserviço apresenta um conjunto disperso de serviços e, comparado ao projeto monolítico, aumenta a possibilidade de falhas em cada nível de serviço. Um determinado microsserviço pode falhar devido a problemas de rede, indisponibilidade dos recursos subjacentes, etc. Um microsserviço indisponível ou sem resposta não deve “derrubar” toda a aplicação baseada em microsserviços. Por isso, os microsserviços devem ser tolerantes a falhas, devem ser capazes de recuperar quando for possível e o cliente deve lidar com isso elegantemente.

Além disso, como os serviços podem falhar a qualquer momento, é importante poder detectar (monitoramento em tempo real) as falhas rapidamente e, se possível, restaurar automaticamente os serviços. Existem vários patterns comumente usados ​​no tratamento de erros, no contexto de microsserviços.

Circuit Breaker

Quando você está fazendo uma chamada externa para um microsserviço, você configura um componente que será responsável por monitorar falhas referentes às chamadas e, quando essas falhas atingem um determinado número de ocorrências, esse componente acusa um erro e para qualquer chamada futura “abre o circuito”, evitando que o chamador fique esperando por muito tempo. Após determinado número de solicitações no estado aberto (que você pode configurar), quando detectar que o microsserviço se restabeleceu, ele altera o circuito de volta para o estado fechado.

Esse pattern é bastante útil para evitar o consumo desnecessário de recursos e os atrasos das solicitações devido a timeouts e também nos dá a chance de monitorar o sistema (com base nos estados de circuitos abertos ativos).

Bulkhead

Como uma aplicação de microsserviço compreende vários microsserviços, as falhas de uma parte da aplicação baseada em microsserviços não devem afetar o restante da aplicação. O pattern do bulkhead se refere a isolar diferentes partes da sua aplicação, de modo que a falha de um serviço em tal parte da aplicação não afeta nenhum dos outros serviços.

Timeout

O pattern de timeout é um mecanismo que permite que você pare de esperar por uma resposta do microsserviço quando achar que esta resposta não virá. Aqui você pode configurar o intervalo de tempo que você deseja aguardar.

Então, onde e como usamos esses patterns com microsserviços? Na maioria dos casos, eles são aplicáveis no nível do Gateway. O que significa que, quando os microsserviços não estão disponíveis ou não estão respondendo, no nível do Gateway, podemos decidir se enviamos a solicitação ao microsserviço usando um pattern de circuit breaker ou de timeout. Além disso, é muito importante ter patterns como bulkhead implementados no nível do Gateway, uma vez que esse é o único ponto de entrada para todas as solicitações do cliente. Assim, uma falha em um determinado serviço não deve afetar a chamada de outros microsserviços.

Além disso, o Gateway pode ser usado como o ponto central para que possamos obter o status e o monitoramento de cada microsserviço, à medida que cada microsserviço é invocado através do Gateway.

Microsserviços, Integração Corporativa, Gerenciamento de API e mais.

Discutimos várias características da arquitetura de microsserviços e como você pode implementá-las no moderno cenário corporativo de TI. No entanto, devemos ter em mente que microsserviços não é uma panaceia. A adaptação cega dos novos conceitos não resolverá seus problemas “reais” de TI da empresa. Como você viu ao longo deste post, há muitas vantagens para os microsserviços e devemos aproveitá-las. Mas também temos que ter em mente que não é realista resolver todos os problemas de TI da empresa usando microsserviços. Por exemplo, a arquitetura de microsserviços promove a eliminação do ESB como o barramento central, mas quando se trata de TI no mundo real, existem muitas aplicações/serviços que não são baseados em microsserviços. Então, para integrar com essas aplicações/serviços, precisamos de algum tipo de barramento de integração. Assim, idealmente, uma abordagem híbrida de microsserviços e outros conceitos arquiteturais corporativos, como integração, seria mais realista.

Espero que isso lhe dê uma ideia muito mais clara sobre como você pode usar os microsserviços em sua empresa.

Referências

Microservices for the Enterprise: Designing, Developing, and Deploying
Kasun Indrasiri e Prabath Siriwardena

http://martinfowler.com/articles/microservices.html
http://techblog.netflix.com/2011/12/making-netflix-api-more-resilient.html 
http://www.infoq.com/articles/seven-uservices-antipatterns   
https://pragprog.com/book/mnee/release-it

Fonte: https://medium.com/microservices-in-practice/microservices-in-practice-7a3e85b6624c

Autor: Kasun Indrasiri

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Newsletter

Insights de tecnologia para você!

Não compartilharemos seu e-mail com terceiros e também prometemos não enviar spams. Ao informar seu e-mail, você concorda com nossa Política de Privacidade.

Conteúdos relacionados

Confira como funciona a Inteligência Artificial Geral, os impactos sociais e éticos dessa tecnologia e o que podemos ...
Veja nesse artigo como evitar drawbacks e interrupções de serviço ao utilizar Kubernetes, maximizando a eficiência.
Descubra adotar a IA generativa nas empresas e potencializar a produtividade e inovação das equipes de TI no desenvol...