Editor – Esta série de artigos em sete partes está agora completa:
Você também pode baixar o conjunto completo de artigos, além de informações sobre a implementação de microsserviços usando o NGINX Plus, como um e-book – Microsserviços: Do design à implantação . Além disso, confira a nova página Soluções de Microsserviços .
O primeiro artigo desta série de sete partes sobre design, construção e implantação de microsserviços apresentou o padrão de arquitetura de microsserviços. Ele discutiu os benefícios e desvantagens do uso de microsserviços e como, apesar da complexidade dos microsserviços, eles geralmente são a escolha ideal para aplicativos complexos. Este é o segundo artigo da série e discutirá a criação de microsserviços usando um API Gateway.
Ao escolher criar seu aplicativo como um conjunto de microsserviços, você precisa decidir como os clientes do seu aplicativo irão interagir com os microsserviços. Com um aplicativo monolítico, há apenas um conjunto de pontos de extremidade (normalmente replicados e com balanceamento de carga). Em uma arquitetura de microsserviços, no entanto, cada microsserviço expõe um conjunto do que normalmente são endpoints granulares. Neste artigo, examinamos como isso afeta a comunicação entre cliente e aplicativo e propomos uma abordagem que usa um API Gateway .
Vamos imaginar que você está desenvolvendo um cliente móvel nativo para um aplicativo de compras. É provável que você precise implementar uma página de detalhes do produto, que exiba informações sobre qualquer produto específico.
Por exemplo, o diagrama a seguir mostra o que você verá ao rolar pelos detalhes do produto no aplicativo móvel Android da Amazon.
Embora este seja um aplicativo para smartphone, a página de detalhes do produto exibe muitas informações. Por exemplo, esta página não só contém informações básicas sobre o produto (como nome, descrição e preço), mas também mostra:
Ao usar uma arquitetura de aplicativo monolítica, um cliente móvel recuperaria esses dados fazendo uma única chamada REST ( GET
api.company.com/productdetails/productId
) para o aplicativo. Um balanceador de carga encaminha a solicitação para uma das N instâncias de aplicativo idênticas. O aplicativo então consultaria várias tabelas do banco de dados e retornaria a resposta ao cliente.
Por outro lado, ao usar a arquitetura de microsserviços, os dados exibidos na página de detalhes do produto pertencem a vários microsserviços. Aqui estão alguns dos microsserviços potenciais que possuem dados exibidos na página de detalhes do produto de exemplo:
Precisamos decidir como o cliente móvel acessa esses serviços. Vamos dar uma olhada nas opções.
Em teoria, um cliente poderia fazer solicitações a cada um dos microsserviços diretamente. Cada microsserviço teria um endpoint público ( https:// serviceName .api.company.name ). Essa URL seria mapeada para o balanceador de carga do microsserviço, que distribui solicitações entre as instâncias disponíveis. Para recuperar os detalhes do produto, o cliente móvel faria solicitações a cada um dos serviços listados acima.
Infelizmente, há desafios e limitações com essa opção. Um problema é a incompatibilidade entre as necessidades do cliente e as APIs detalhadas expostas por cada um dos microsserviços. O cliente neste exemplo precisa fazer sete solicitações separadas. Em aplicações mais complexas, pode ser necessário fazer muito mais. Por exemplo, a Amazon descreve como centenas de serviços estão envolvidos na renderização de sua página de produto. Embora um cliente pudesse fazer tantas solicitações por uma LAN, provavelmente seria muito ineficiente pela Internet pública e definitivamente impraticável por uma rede móvel. Essa abordagem também torna o código do cliente muito mais complexo.
Outro problema com o cliente chamando diretamente os microsserviços é que alguns podem usar protocolos que não são amigáveis à web. Um serviço pode usar o Thrift binary RPC enquanto outro serviço pode usar o protocolo de mensagens AMQP. Nenhum dos protocolos é particularmente amigável ao navegador ou firewall e é melhor usado internamente. Um aplicativo deve usar protocolos como HTTP e WebSocket fora do firewall.
Outra desvantagem dessa abordagem é que ela dificulta a refatoração dos microsserviços. Com o tempo, podemos querer alterar a forma como o sistema é particionado em serviços. Por exemplo, podemos mesclar dois serviços ou dividir um serviço em dois ou mais serviços. No entanto, se os clientes se comunicarem diretamente com os serviços, executar esse tipo de refatoração pode ser extremamente difícil.
Por causa desses tipos de problemas, raramente faz sentido que os clientes falem diretamente com os microsserviços.
Normalmente, uma abordagem muito melhor é usar o que é conhecido como API Gateway . Um API Gateway é um servidor que é o único ponto de entrada no sistema. É semelhante ao padrão Facade do design orientado a objetos. O API Gateway encapsula a arquitetura interna do sistema e fornece uma API personalizada para cada cliente. Ele pode ter outras responsabilidades, como autenticação, monitoramento, balanceamento de carga, armazenamento em cache, modelagem e gerenciamento de solicitações e tratamento de resposta estática.
O diagrama a seguir mostra como um API Gateway normalmente se encaixa na arquitetura:
O API Gateway é responsável pelo roteamento de solicitações, composição e tradução de protocolos. Todas as solicitações dos clientes passam primeiro pelo API Gateway. Em seguida, ele encaminha as solicitações para o microsserviço apropriado. O API Gateway geralmente manipula uma solicitação invocando vários microsserviços e agregando os resultados. Ele pode traduzir entre protocolos da web, como HTTP e WebSocket, e protocolos não amigáveis à web que são usados internamente.
O API Gateway também pode fornecer a cada cliente uma API personalizada. Ele normalmente expõe uma API de granulação grossa para clientes móveis. Considere, por exemplo, o cenário de detalhes do produto. O API Gateway pode fornecer um endpoint ( /productdetails?productid= xxx ) que permite que um cliente móvel recupere todos os detalhes do produto com uma única solicitação. O API Gateway manipula a solicitação invocando os vários serviços – informações do produto, recomendações, avaliações, etc. – e combinando os resultados.
Um ótimo exemplo de um API Gateway é o Netflix API Gateway . O serviço de streaming Netflix está disponível em centenas de tipos diferentes de dispositivos, incluindo televisores, decodificadores, smartphones, consoles de jogos, tablets, etc. Inicialmente, a Netflix tentou fornecer uma API única para seu serviço de streaming. No entanto, eles descobriram que não funcionava bem devido à diversidade de dispositivos e às suas necessidades específicas. Hoje, eles usam um API Gateway que fornece uma API personalizada para cada dispositivo executando um código adaptador específico do dispositivo. Um adaptador normalmente lida com cada solicitação invocando em média seis a sete serviços de backend. O Netflix API Gateway processa bilhões de solicitações por dia.
Como você pode esperar, usar um API Gateway tem vantagens e desvantagens. Um grande benefício de usar um API Gateway é que ele encapsula a estrutura interna do aplicativo. Em vez de precisar invocar serviços específicos, os clientes simplesmente conversam com o gateway. O API Gateway fornece a cada tipo de cliente uma API específica. Isso reduz o número de viagens de ida e volta entre o cliente e o aplicativo. Também simplifica o código do cliente.
O API Gateway também tem algumas desvantagens. É mais um componente altamente disponível que deve ser desenvolvido, implantado e gerenciado. Também existe o risco de que o API Gateway se torne um gargalo de desenvolvimento. Os desenvolvedores devem atualizar o API Gateway para expor os endpoints de cada microsserviço. É importante que o processo de atualização do API Gateway seja o mais leve possível. Caso contrário, os desenvolvedores serão forçados a esperar na fila para atualizar o gateway. Apesar dessas desvantagens, no entanto, para a maioria das aplicações do mundo real, faz sentido usar um API Gateway.
Agora que analisamos as motivações e as compensações para usar um API Gateway, vamos analisar vários problemas de design que você precisa considerar.
Apenas algumas empresas operam na escala da Netflix e precisam lidar com bilhões de solicitações por dia. Entretanto, para a maioria das aplicações, o desempenho e a escalabilidade do API Gateway costumam ser muito importantes. Faz sentido, portanto, construir o API Gateway em uma plataforma que suporte E/S assíncronas e não bloqueantes. Há uma variedade de tecnologias diferentes que podem ser usadas para implementar um API Gateway escalável. Na JVM, você pode usar uma das estruturas baseadas em NIO, como Netty, Vertx, Spring Reactor ou JBoss Undertow. Uma opção popular não JVM é o Node.js, que é uma plataforma construída no mecanismo JavaScript do Chrome. Outra opção é usar o NGINX Plus . O NGINX Plus oferece um servidor web e proxy reverso maduro, escalável e de alto desempenho que é facilmente implantado, configurado e programado. O NGINX Plus pode gerenciar autenticação, controle de acesso, solicitações de balanceamento de carga, respostas de cache e fornece verificações de integridade e monitoramento com reconhecimento de aplicativo.
O API Gateway lida com algumas solicitações simplesmente roteando-as para o serviço de backend apropriado. Ele lida com outras solicitações invocando vários serviços de backend e agregando os resultados. Com algumas solicitações, como uma solicitação de detalhes do produto, as solicitações para serviços de backend são independentes umas das outras. Para minimizar o tempo de resposta, o API Gateway deve executar solicitações independentes simultaneamente. Às vezes, porém, há dependências entre as solicitações. O API Gateway pode primeiro precisar validar a solicitação chamando um serviço de autenticação antes de rotear a solicitação para um serviço de backend. Da mesma forma, para buscar informações sobre os produtos na lista de desejos de um cliente, o API Gateway deve primeiro recuperar o perfil do cliente que contém essas informações e, em seguida, recuperar as informações de cada produto. Outro exemplo interessante de composição de API é o Netflix Video Grid .
Escrever código de composição de API usando a abordagem tradicional de retorno de chamada assíncrona rapidamente leva você ao inferno do retorno de chamada. O código ficará confuso, difícil de entender e propenso a erros. Uma abordagem muito melhor é escrever o código do API Gateway em um estilo declarativo usando uma abordagem reativa. Exemplos de abstrações reativas incluem Future em Scala, CompletableFuture em Java 8 e Promise em JavaScript. Há também o Reactive Extensions (também chamado de Rx ou ReactiveX), que foi originalmente desenvolvido pela Microsoft para a plataforma .NET. A Netflix criou o RxJava para a JVM especificamente para uso em seu API Gateway. Há também o RxJS para JavaScript, que roda tanto no navegador quanto no Node.js. Usar uma abordagem reativa permitirá que você escreva código de API Gateway simples, mas eficiente.
Um aplicativo baseado em microsserviços é um sistema distribuído e deve usar um mecanismo de comunicação entre processos. Existem dois estilos de comunicação entre processos. Uma opção é usar um mecanismo assíncrono baseado em mensagens. Algumas implementações usam um corretor de mensagens, como JMS ou AMQP. Outros, como o Zeromq, não têm corretores e os serviços se comunicam diretamente. O outro estilo de comunicação entre processos é um mecanismo síncrono, como HTTP ou Thrift. Um sistema normalmente usará estilos assíncronos e síncronos. Ele pode até usar múltiplas implementações de cada estilo. Consequentemente, o API Gateway precisará oferecer suporte a uma variedade de mecanismos de comunicação.
O API Gateway precisa saber a localização (endereço IP e porta) de cada microsserviço com o qual ele se comunica. Em um aplicativo tradicional, você provavelmente conseguiria conectar os locais, mas em um aplicativo moderno de microsserviços baseado em nuvem, esse é um problema não trivial. Serviços de infraestrutura, como um corretor de mensagens, geralmente terão um local estático, que pode ser especificado por meio de variáveis de ambiente do sistema operacional. No entanto, determinar a localização de um serviço de aplicativo não é tão fácil. Os serviços de aplicativos têm locais atribuídos dinamicamente. Além disso, o conjunto de instâncias de um serviço muda dinamicamente devido ao dimensionamento automático e às atualizações. Consequentemente, o API Gateway, como qualquer outro cliente de serviço no sistema, precisa usar o mecanismo de descoberta de serviço do sistema: Descoberta do lado do servidor ou Descoberta do lado do cliente . Um artigo posterior descreverá a descoberta de serviços com mais detalhes. Por enquanto, vale a pena observar que, se o sistema usar o Client‑Side Discovery, o API Gateway deverá ser capaz de consultar o Service Registry , que é um banco de dados de todas as instâncias de microsserviços e seus locais.
Outro problema que você precisa resolver ao implementar um API Gateway é o problema de falha parcial. Esse problema surge em todos os sistemas distribuídos sempre que um serviço chama outro serviço que está respondendo lentamente ou não está disponível. O API Gateway nunca deve bloquear indefinidamente esperando por um serviço downstream. No entanto, a forma como ele lida com a falha depende do cenário específico e de qual serviço está falhando. Por exemplo, se o serviço de recomendação não responder no cenário de detalhes do produto, o API Gateway deverá retornar o restante dos detalhes do produto ao cliente, pois eles ainda são úteis para o usuário. As recomendações podem estar vazias ou substituídas por, por exemplo, uma lista fixa dos dez melhores. No entanto, se o serviço de informações do produto não responder, o API Gateway deverá retornar um erro ao cliente.
O API Gateway também pode retornar dados armazenados em cache, se estiverem disponíveis. Por exemplo, como os preços dos produtos mudam com pouca frequência, o API Gateway pode retornar dados de preços armazenados em cache se o serviço de preços não estiver disponível. Os dados podem ser armazenados em cache pelo próprio API Gateway ou armazenados em um cache externo, como Redis ou Memcached. Ao retornar dados padrão ou dados armazenados em cache, o API Gateway garante que falhas do sistema não afetem a experiência do usuário.
Netflix Hystrix é uma biblioteca incrivelmente útil para escrever código que invoca serviços remotos. O Hystrix esgota o tempo limite das chamadas que excedem o limite especificado. Ele implementa um padrão de disjuntor , que impede que o cliente espere desnecessariamente por um serviço que não responde. Se a taxa de erro de um serviço exceder um limite especificado, o Hystrix desarma o disjuntor e todas as solicitações falharão imediatamente por um período de tempo especificado. O Hystrix permite que você defina uma ação de fallback quando uma solicitação falha, como ler de um cache ou retornar um valor padrão. Se você estiver usando a JVM, você definitivamente deve considerar usar o Hystrix. E, se você estiver executando em um ambiente não JVM, deverá usar uma biblioteca equivalente.
Para a maioria dos aplicativos baseados em microsserviços, faz sentido implementar um API Gateway, que atua como um único ponto de entrada em um sistema. O API Gateway é responsável pelo roteamento de solicitações, composição e tradução de protocolos. Ele fornece a cada um dos clientes do aplicativo uma API personalizada. O API Gateway também pode mascarar falhas nos serviços de backend retornando dados em cache ou padrão. No próximo artigo da série, veremos a comunicação entre serviços.
Editor – Esta série de artigos em sete partes está agora completa:
Você também pode baixar o conjunto completo de artigos, além de informações sobre a implementação de microsserviços usando o NGINX Plus, como um e-book – Microsserviços: Do design à implantação .
Para uma análise detalhada de casos de uso adicionais, consulte nossa série de blogs em três partes, Implantando o NGINX Plus como um gateway de API :
O blogueiro convidado Chris Richardson é o fundador do CloudFoundry.com original, um dos primeiros Java PaaS (Plataforma como Serviço) para Amazon EC2. Agora, ele presta consultoria a organizações para melhorar a maneira como elas desenvolvem e implantam aplicativos. Ele também escreve regularmente sobre microsserviços em http://microservices.io .
"Esta postagem do blog pode fazer referência a produtos que não estão mais disponíveis e/ou não têm mais suporte. Para obter as informações mais atualizadas sobre os produtos e soluções F5 NGINX disponíveis, explore nossa família de produtos NGINX . O NGINX agora faz parte do F5. Todos os links anteriores do NGINX.com redirecionarão para conteúdo semelhante do NGINX no F5.com."