Atualizado em 11/02/2021!
Recentemente escrevi uma série de artigos sobre arquitetura de microservices usando Node.js e MongoDB. Na situação atual desta série temos alguns microservices criados e, com isso, uma complexidade que não existia nos webservices monolíticos de antigamente: múltiplos endpoints de múltiplos serviços para uma única aplicação.
Será que o(s) client(s) deveriam conhecer as especificidades de cada microservice? E no caso de algoritmos que são padrões a todos os microservices (como autenticação e autorização), devem ser repetidas em todos microservices?
Como resolver estas e outras questões sem gambiarra, de maneira corporativa? Usando um API Gateway, conforme já comentei no artigo sobre boas práticas com microservices.
Você verá neste artigo:
Se quiser ver este mesmo tutorial em formato de vídeo aula, confira o meu Curso de Node.js e MongoDB!
#1 – API Gateway e API Manager
Resumidamente um API Gateway fornece um ponto de acesso único à sua arquitetura de microservices. Não importa quantos microservices você tenha, colocando um API Gateway à frente deles você terá uma única URL para se preocupar. O API Gateway por sua vez roteia e gerencia o tráfego de requisições para os microservices de destino.
Já um API Manager é um API Gateway mais ‘bombado’, que além de atuar como proxy realiza toda uma governança das chamadas realizadas aos microservices, como analytics, versionamento de APIs, caching, dashboards, segurança, transformação de dados, agregação de dados, etc.
Uma abordagem possível é ter um API Gateway por diferente client, como na imagem abaixo:
Uma solução bem comum no mercado é usar um proxy reverso como nginx, mas Node.js também é um excelente opção para construção de API Gateways quando se deseja um controle maior das requisições, permitindo fazer algo mais próximo de um API Manager sob medida. É exatamente o que fez a Netflix, que construiu um API Gateway em Node.js para ficar na frente das suas centenas de APIs Java, como mostra o diagrama abaixo:
Especialmente para clientes mobile, que possuem severas limitações de latência e qualidade de conexão à Internet, um API Gateway pode simplificar em uma única chamada mobile, diversas requisições aos microservices que, acontecendo na rede local do datacenter, serão muito mais velozes do que se o dispositivo móvel tivesse de fazer diversas chamadas.
A diferença entre API Gateway e API Manager é tênue, uma vez que há diversos fabricantes e nomenclaturas diferentes no mercado. O termo mais comumente utilizado é de API Gateway, geralmente sendo chamados de API Managers as soluções comerciais corporativas.
#2 – O que vamos fazer
A ideia deste tutorial é fazer um API Gateway simples em Node.js, seguindo a arquitetura abaixo:
Nesta arquitetura, o API Gateway recebe e roteia as requisições para microservices dentro de uma DMZ (Zona Desmilitarizada ou Zona de Perímetro), um conceito de segurança da informação para proteger a rede da empresa dos serviços e vice-versa.
Assim, nosso cliente somente conhecerá uma API, que é a API Gateway, podendo existir muitos outros microservices por trás dele. Essa abordagem é especialmente interessante quando estamos refatorando serviços monolíticos para microservices: podemos substituir as chamadas ao serviço antigo para chamadas ao API Gateway e roteamos para o serviço antigo. Conforme o time for ‘escamando’ o serviço antigo em microservices, vamos ajustando no API Gateway para chamar ora o serviço antigo, ora os novos microservices. O diagrama abaixo mostra isso:
Mais pra frente podemos aproveitar esta centralização das requisições para adicionar segurança à todas as chamadas como autenticação e rate limit (controle de uso das APIs, para evitar exageros).
Para executar este tutorial na prática é importante que você tenha alguns microservices prontos na sua máquina, no mínimo dois. Se você não tiver, nos fontes deste tutorial eu inclui dois micro serviços fake que sempre retornam os mesmos dados mockados, para que você possa testar. No entanto, o mais recomendado é que você realize os tutoriais de microservices que estão aqui no blog para realmente aprender o tópico completo.
#3 – Criando a API Gateway
Por incrível que pareça, criar o esqueleto de um API Gateway é muito simples.
Vamos começar criando uma pasta para o nosso projeto, chamado api-gateway. Dentro dessa pasta crie um arquivo index.js e via terminal, navegue até a pasta do api-gateway e rode o comando ‘npm init’ para inicializar este projeto Node.js.
Configure a sua aplicação através do assistente do npm init para que ele crie o package.json. Agora que temos um package.json, via terminal vamos mandar instalar as dependências que vamos precisar em nosso projeto:
1 2 3 |
npm i express morgan express-http-proxy |
Esse comando vai instalar as seguintes dependências:
- express: nosso pacote para criar web APIs e web apps facilmente;
- morgan: o logger que usaremos para saber o que está acontecendo com nosso API Gateway no terminal;
- express-http-proxy: pacote para redirecionar requisições para os microservices;
O código abaixo mostra o que é possível fazer em poucas linhas:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
//index.js const httpProxy = require('express-http-proxy'); const express = require('express'); const app = express(); var logger = require('morgan'); app.use(logger('dev')); function selectProxyHost(req) { if (req.path.startsWith('/movies')) return 'http://localhost:3000/'; else if (req.path.startsWith('/cinemas')) return 'http://localhost:3001/'; } app.use((req, res, next) => { httpProxy(selectProxyHost(req))(req, res, next); }); app.listen(10000, () => { console.log('API Gateway running!'); }); |
Para quem já criou uma API em Express antes não há nada excepcionalmente novo aqui. Eu configurei os pacotes nas primeiras linhas, usei o express-http-proxy para criar proxies de chamadas para dois serviços fake (disponíveis junto dos fontes no final deste artigo), um de movies e outro de cinemas (que ensino a criar neste tutorial).
A parte de mapeamento das URLs é o mesmo padrão do Express, mas aqui o segredo está na função selectProxyHost, onde eu defino com base no path recebido, a URL de destino. Querendo tornar essa função dinâmica, recomendo salvar as regras de roteamento como chave-valor em um banco Redis que é muito rápido e excelente para esta finalidade.
As duas últimas linhas criam o servidor HTTP para que ele passe a escutar na porta 10000, deixando as demais para os micro serviços que serão roteados por esse API Gateway, que será a rota default de todos os fronts da sua aplicação.
#4 – Testando e indo além
Para subir as APIs fake, rode um ‘npm install’ nelas primeiro para instalar as dependências e depois um ‘npm start’ em cada uma, sendo que movies está configurada pra rodar na porta 3000, e cinemas na 3001.
Depois que estiver com as duas APIs fake rodando, experimente testá-las no navegador para ver que elas apenas listam sempre os mesmos dados mockados.
Depois, suba o seu api-gateway mandando executar o index.js. Teste o api-gateway diretamente no navegador fazendo as mesmas chamadas que faria aos microservices originais. Se tudo ocorreu bem, o retorno será o mesmo que nos microservices originais, sem qualquer diferença aparente, de forma transparente para o cliente.
E justamente essa é a grande vantagem de se trabalhar com um API Gateway!
Como o Express funciona como um middleware de requisições, é muito simples e prático adicionar camadas adicionais de execução antes de repassar a requisição aos microservices (como segurança com JWT ou cache com Redis), permitindo todo tipo de gerenciamento de APIs que você imaginar.
Abordagens mais profissionais vão ter o mapeamento parametrizável através de banco de dados para que seja simples de adicionar novas APIs e rotas ao Gateway sem ter de mexer em programação.
Outra dica é subir o seu API Gateway em cluster, para garantir uma alta capacidade de processamento em máquinas que possuem múltiplas CPUs e que normalmente o Event Loop single thread não “aproveita”:
De qualquer forma espero que este artigo tenha lhe dado uma ideia de como fazer essa camada importantíssima na arquitetura de microservices. Se quiser aprender mais boas práticas com microservices, leia este artigo.
Até a próxima!
Curtiu o post? Então clica no banner abaixo e dá uma conferida no meu livro sobre microservices com Node.js!
Olá, tudo bem?
O que você achou deste conteúdo? Conte nos comentários.