Parte 1: Como construir um gateway de API de Microservices usando OpenResty

API7.ai

January 20, 2023

OpenResty (NGINX + Lua)

Neste artigo, vamos avançar para os capítulos sobre OpenResty em ação. Usarei três capítulos para apresentar como implementar um gateway de API para microsserviços. Nesse processo, não apenas envolveremos o conhecimento de OpenResty que aprendemos anteriormente, mas também mostrarei como construir um novo produto e projeto de código aberto do zero, considerando múltiplas dimensões, como indústria, produto e seleção de tecnologia.

O que um Gateway de API para Microsserviços faz?

Vamos primeiro entender o papel do gateway de API para microsserviços. A imagem abaixo é uma breve descrição:

Gateway de API para Microsserviços

Como todos sabemos, o gateway de API não é um conceito novo. Ele existe há mais de dez anos. Sua função principal é servir como a entrada de tráfego e processar solicitações relacionadas ao negócio de forma unificada. Assim, as solicitações podem ser processadas de maneira mais segura, rápida e precisa. Ele possui as seguintes funções tradicionais:

  • Proxy reverso e balanceamento de carga, que são consistentes com o posicionamento e as funções do NGINX;
  • Funções dinâmicas, como upstream dinâmico, certificado SSL dinâmico e limitação de taxa e corrente em tempo de execução, que são funções que a versão de código aberto do NGINX não possui;
  • Verificações de saúde ativas e passivas dos upstreams, além de circuit breakers de serviço;
  • Expansão do gateway de API para se tornar uma plataforma de gerenciamento de API de ciclo completo.

Nos últimos anos, o tráfego relacionado ao negócio não é mais iniciado apenas por clientes de PC e navegadores, mas também por dispositivos móveis e IoT. Com a popularização do 5G no futuro, esse tráfego aumentará. Ao mesmo tempo, à medida que a estrutura da arquitetura de microsserviços muda, o tráfego entre os serviços também começa a crescer exponencialmente. Nesse novo cenário de negócios, naturalmente surgiram funções mais avançadas no gateway de API:

  1. Amigável ao cloud-native, a arquitetura deve se tornar leve e fácil de ser conteinerizada.
  2. Integração com componentes de monitoramento e estatísticas como Prometheus, Zipkin e SkyWalking.
  3. Suporte a proxy gRPC e conversão de protocolo entre HTTP e gRPC, convertendo solicitações HTTP do usuário em solicitações gRPC internas.
  4. Assumir o papel de OpenID Relying Party, conectando-se a serviços de provedores de autenticação como Auth0 e Okta, e tratando a segurança do tráfego como prioridade máxima.
  5. Implementar Serverless executando funções do usuário dinamicamente em tempo de execução, tornando os nós de borda do gateway mais flexíveis.
  6. Não bloquear usuários e suportar arquitetura de implantação em nuvem híbrida.
  7. O nó do gateway deve ser independente de estado e poder expandir e reduzir conforme necessário.

Quando um gateway de API para microsserviços possui as funções mencionadas acima, o serviço do usuário pode se concentrar apenas no negócio em si. Aquelas funções que não estão relacionadas à implementação do negócio podem ser resolvidas no nível do gateway independente. Por exemplo, descoberta de serviços, circuit breaker, autenticação, limitação de taxa, estatísticas, análise de desempenho, etc.

Dessa perspectiva, o Gateway de API pode substituir todas as funções do NGINX e lidar com o tráfego norte-sul; também pode desempenhar o papel do plano de controle do Istio e do plano de dados do Envoy para lidar com o tráfego leste-oeste.

Por que reinventar a roda?

Como o status do gateway de API para microsserviços é tão importante, ele sempre foi um campo de batalha, e os gigantes tradicionais de TI estão nesse campo há muito tempo. De acordo com o API Lifecycle Report da Gartner de 2018, Google, CA, IBM, Red Hat e Salesforce são os principais fabricantes, e o Apache APISIX, mais familiar aos desenvolvedores, está entre os visionários.

Então, a pergunta é: por que precisamos reinventar uma nova roda?

Simplificando, isso ocorre porque nenhum dos gateways de API atuais para microsserviços atende às nossas necessidades. Vamos primeiro olhar para os produtos comerciais de código fechado. Eles têm funções completas, cobrindo todo o ciclo de vida de gerenciamento de API, SDK multilíngue, documentação, testes e lançamento, e oferecem serviços SaaS. Alguns são integrados à nuvem pública, o que é muito conveniente de usar. Mas, ao mesmo tempo, eles também trazem dois pontos problemáticos.

O primeiro ponto problemático é o bloqueio da plataforma. O gateway de API é a entrada do tráfego de negócios. Diferente do tráfego não relacionado ao negócio acelerado por CDNs, como imagens e vídeos, que podem ser migrados livremente, o gateway de API estará vinculado a muita lógica relacionada ao negócio. Uma vez que você usa uma solução de código fechado, é difícil migrar para outras plataformas de forma suave e com baixo custo.

O segundo ponto problemático é a impossibilidade de desenvolvimento adicional. Geralmente, empresas de médio e grande porte têm necessidades únicas e precisam de desenvolvimento personalizado, mas, nesse momento, você só pode contar com o fabricante e não pode fazer desenvolvimento secundário.

Essa é uma das razões pelas quais as soluções de gateway de API de código aberto se tornaram populares. No entanto, os produtos de código aberto existentes não são onipotentes e também têm muitas deficiências:

  1. Dependem de bancos de dados relacionais como PostgreSQL e MySQL. Dessa forma, o nó do gateway só pode consultar o banco de dados quando há mudanças na configuração. Isso não apenas faz com que a configuração demore a entrar em vigor, mas também adiciona complexidade ao código, tornando-o difícil de entender. Ao mesmo tempo, o banco de dados também se torna um ponto único e um gargalo de desempenho do sistema, o que não garante alta disponibilidade geral. Se você usar o gateway de API em um ambiente Kubernetes, o banco de dados relacional será mais complicado, o que não é favorável à escalabilidade rápida.
  2. Plugins não podem ser carregados dinamicamente. Quando você adiciona um novo plugin ou modifica o código de um plugin existente, deve recarregar o serviço para que ele entre em vigor. Isso é semelhante à necessidade de recarregar após modificar a configuração do NGINX, o que afeta as solicitações do usuário.
  3. A estrutura do código é complexa e difícil de entender. Alguns projetos de código aberto fizeram encapsulamento orientado a objetos em várias camadas, e algumas lógicas simples se tornaram obscuras. Mas, para o cenário de gateway de API, a expressão direta será mais clara e eficiente, e também mais favorável ao desenvolvimento secundário.

Portanto, precisamos de um gateway de API mais leve, nativo em nuvem e amigável ao desenvolvimento. Claro, não podemos construir um carro com as portas fechadas. Precisamos entender profundamente as características dos gateways de API existentes. Nesse momento, o panorama da Cloud Native Software Foundation (CNCF) é uma boa referência:

panorama da CNCF

Componentes e Conceitos Principais do Gateway de API

Claro, antes de implementá-lo, precisamos entender os componentes principais do Gateway de API. De acordo com as funções do gateway de API que mencionamos anteriormente, ele precisa de pelo menos os seguintes componentes para começar a funcionar.

O primeiro é Route. Ele corresponde à solicitação do cliente definindo algumas regras, depois carrega e executa o plugin correspondente de acordo com o resultado da correspondência e encaminha a solicitação para o upstream especificado. Essas regras de correspondência de rota podem ser compostas por host, uri, header, etc. O location familiar no NGINX é uma implementação de roteamento.

O segundo é o plugin, a alma do gateway de API. Funções como autenticação, limitação de tráfego e taxa, restrição de IP, Prometheus, Zipkin, etc., são todas implementadas por meio de plugins. Como é um plugin, ele precisa ser plug-and-play; além disso, os plugins não podem interagir entre si. Assim como construímos blocos de Lego, precisamos usar regras uniformes e interfaces de desenvolvimento acordadas para interagir com a camada inferior.

Em seguida, temos o schema. Como é um gateway para processar APIs, é necessário verificar o formato da API, como tipos de dados, conteúdo permitido dos campos, campos que devem ser enviados, etc. Nesse momento, é necessária uma camada de schema para definição e verificação unificada e independente.

Por último, temos o armazenamento. Ele é usado para armazenar várias configurações do usuário e é responsável por enviar para todos os nós do gateway quando há uma mudança. Esse é um componente básico muito crítico na camada inferior. Sua escolha determina como os plugins da camada superior são escritos, se o sistema pode manter alta disponibilidade e escalabilidade, etc., então precisamos tomar uma decisão cuidadosa.

Além disso, sobre esses componentes principais, também precisamos abstrair vários conceitos comuns de gateways de API, que são comuns entre diferentes gateways de API.

Route

Vamos falar primeiro sobre Route. Uma rota contém três partes: condições de correspondência, plugins vinculados e upstream, como mostrado na figura abaixo:

Route

Podemos completar todas as configurações diretamente em Route, o que é o mais fácil. Mas, no caso de muitas APIs e upstreams, isso causará muitas configurações duplicadas. Nesse momento, precisamos dos dois conceitos de Service e Upstream para fazer uma camada de abstração.

Service

Vamos olhar para Service a seguir. Ele é uma abstração de um tipo específico de API e também pode ser entendido como uma abstração de um grupo de Routes. Geralmente, ele tem uma correspondência 1:1 com serviços upstream, e a relação entre Routes e Services é geralmente N:1. Também usei uma imagem para representar:

Service

Por meio dessa camada de abstração de Service, podemos separar os Plugins e Upstreams duplicados. Dessa forma, quando o Plugin e o Upstream mudam, precisamos apenas modificar o Service em vez de modificar os dados vinculados em vários Routes.

Upstream

Por fim, vamos falar sobre Upstream. Continuando com o exemplo acima, se os upstreams nos dois Routes forem os mesmos, mas os plugins vinculados forem diferentes, então podemos abstrair os upstreams separadamente, como mostrado na figura abaixo:

Upstream

Dessa forma, quando o nó upstream muda, o Route não tem conhecimento, e tudo é processado dentro do Upstream.

A partir do processo de derivação desses três conceitos principais, também podemos ver que essas abstrações são baseadas em cenários práticos de uso, e não em imaginação. Elas se aplicam a todos os gateways de API, independentemente das soluções técnicas específicas.

Resumo

Neste artigo, apresentamos o papel, as funções, os componentes principais e os conceitos abstratos do gateway de API para microsserviços, que são a base do gateway de API.

Aqui está uma pergunta para você refletir: "Em relação ao tráfego tradicional norte-sul e ao tráfego leste-oeste entre microsserviços, você acha que o gateway de API pode lidar com ambos?" Se você já está usando um gateway de API, também pode anotar seus pensamentos sobre a seleção de tecnologia. Sinta-se à vontade para se comunicar e discutir, e você é bem-vindo a compartilhar este artigo com seus colegas e amigos para aprender e progredir juntos.

Próximo: Parte 2: Como Construir um Gateway de API para Microsserviços Usando OpenResty Parte 3: Como Construir um Gateway de API para Microsserviços Usando OpenResty