Como tornar qualquer aplicativo NodeJS sem servidor

Espero que você ame o Serverless tanto quanto eu, porque este é mais um post sobre esse tópico.

Agora, se estamos falando de uma API REST simples sem servidor, sua configuração é bastante óbvia no AWS: Lambda + API Gateway.

Mas e quanto a outros (micro) serviços que seu back-end pode ter? Você sabe, não é a melhor ideia colocar todo o código do aplicativo em uma única função monolítica do AWS Lambda.

O desafio

Queremos implantar facilmente módulos de aplicativos como microsserviços sem servidor, que também precisam se comunicar. De preferência, a comunicação entre serviços deve ser regulada por algum tipo de ACL.

Tentativa 1. Gateway da API

Este é o primeiro pensamento que tive quando estava tentando resolver o problema: apenas exponha todos os microsserviços via API Gateway. O problema é ... As APIs criadas são públicas.

Por que isso é um problema? Por exemplo, não queremos que um serviço de cobrança seja exposto a todo o mundo, mesmo que o acesso seja restrito usando algum tipo de autorização.

Bem, você pode tornar a API privada, mas as políticas de segurança são bastante limitadas:

Você pode usar políticas de recursos do API Gateway para permitir que sua API seja chamada com segurança por:
* usuários de uma conta especificada da AWS
* intervalos de endereços IP de origem especificados ou blocos CIDR
* nuvens privadas virtuais (VPCs) especificadas ou pontos de extremidade de VPC (em qualquer conta)

Isso torna bastante problemático controlar as comunicações entre esses serviços. A única maneira de fazer isso aqui é colocando serviços em VPCs separados, muito trabalho.

Tentativa 2. Lambda

Por que não colocamos todos os microsserviços em um AWS Lambda separado? Isso resolverá o problema?

Sim, na verdade, será um microsserviço sem servidor e você poderá usar as políticas do IAM para ajustar os acessos entre os serviços, mas ... Não é "fácil".

Sei que hoje em dia é bastante normal ter uma pequena função como sua unidade de implantação. E, no caso em que seu serviço possui mais de 1 ponto de extremidade / método / função, é considerado bom implementá-lo como várias Lambdas.

Entendo as vantagens disso, mas você sacrifica a facilidade de manutenção e desenvolvimento. Além disso, eu realmente não gosto da ideia de ter um serviço implantado como um conjunto de funções Lambda. Imagine, várias funções separadas que lidam com cobrança? Não é mais um contexto limitado. Embora existam casos em que essa granularidade possa ser útil, é um caso raro.

Tentativa 3. Lambda gorda

Podemos realmente implantar um conjunto de pontos de extremidade como um único Lambda (sem usar o API Gateway, é claro)?

Se pudéssemos fazer isso, obteríamos todos os benefícios da opção anterior, mas também poderíamos escolher a granularidade de nossas unidades de implantação.

Do jeito que eu quero, é o seguinte: cada serviço implementável deve ser um objeto JS simples e antigo, com métodos. Isso é bastante trivial, adicionando algumas linhas de código de cola entre seu objeto e o AWS Lambda.

Aqui está a minha implementação: aws-rpc. Este módulo nodejs expõe a função lambdaHandler, onde você passa um objeto, e é automagicamente exposto a qualquer pessoa que possa acessar o Lambda:

import {lambdaHandler} de 'aws-rpc';
import {TestServiceImpl} de './TestServiceImpl';
// esta é sua unidade de implantação
// é isso que você especifica como função manipuladora do Lambda
manipulador const de exportação = lambdaHandler (new TestServiceImpl ());

Agora, você pode implantar "manipulador" como AWS Lambda. Aqui está como você chama seus métodos:

import {TestService} de './TestService';
cliente const = aguardar createClient  ("LambdaName", "test");
console.log (aguarde client.test ());

Observe que, para poder gerar métodos para o objeto stub do cliente, você deve passar todos os nomes dos métodos para createClient, como fizemos no exemplo.

Isso é necessário porque o JS não possui nenhuma informação de tempo de execução sobre as interfaces TypeScript. Eu poderia implementá-lo usando classes abstratas, mas não gosto disso ¯ \ _ (ツ) _ / ¯.

Bônus! Você pode executar tudo localmente!

Acredito que é muito importante ter o seu ambiente de desenvolvimento local o mais confortável possível. É por isso que também adicionei a capacidade de executar o serviço e o cliente localmente sem implantar nada na AWS (consulte as funções runService e createClient). Para exemplos, consulte o repositório no GitHub.

Sumário

É muito fácil se perder nos serviços que os provedores de nuvem oferecem e administrar sua infraestrutura de forma excessiva.

Eu sempre escolho a solução mais simples e explícita que consigo pensar. Além disso, lembre-se sempre de que muitas técnicas e práticas podem ser reutilizadas em outras plataformas (a idéia do NodeJS Lambda gordo é inspirada nos chamados jars gordos do mundo Java).

Se você gostou deste tópico, verifique estes também:

  • Você precisa aprender a criar a melhor arquitetura sem servidor
  • Como criar um pipeline de CI / CD gratuito sem servidor: 3 exemplos fáceis
  • Como replicar facilmente o DynamoDB entre regiões
  • Como fazer uma aplicação multirregional (e pagar zero)
  • Torne qualquer Java Web App sem servidor

Comentários, curtidas e compartilhamentos são muito apreciados. Felicidades!