Hvordan lage noen NodeJS-appserver

Jeg håper du elsker Serverless så mye som jeg fordi dette er enda et innlegg om det emnet.

Hvis vi nå snakker om et enkelt serverløst REST API, er oppsettet ditt ganske tydelig på AWS: Lambda + API Gateway.

Men hva med andre (mikro) tjenester som din backend kan ha? Du vet, det er ikke den beste ideen å sette all søknadskoden din i en enkelt monolitisk AWS Lambda-funksjon.

Utfordringen

Vi ønsker å distribuere applikasjonsmoduler som serverløse mikroservices, som også trenger å kommunisere med hverandre. Fortrinnsvis bør kommunikasjonen mellom tjenester reguleres av en slags ACL.

Forsøk 1. API Gateway

Dette er den første tanken som jeg hadde da jeg prøvde å løse problemet: bare utsett alle mikroservicene via API Gateway. Problemet er ... De opprettede API-ene er offentlige.

Hvorfor er dette et problem? For eksempel ønsker vi ikke å ha en fakturatjeneste som skal eksponeres for hele verden, selv om tilgangen er begrenset ved hjelp av en slags autorisasjon.

Vel, du kan gjøre API-en privat, men sikkerhetspolicyene er ganske begrensede:

Du kan bruke API Gateway-ressurspolitikk for å tillate at APIet ditt påberopes sikkert av:
* brukere fra en spesifisert AWS-konto
* spesifiserte kilde-IP-adresseområder eller CIDR-blokker
* spesifiserte virtuelle private skyer (VPC) eller VPC endpoints (i hvilken som helst konto)

Dette gjør det ganske plagsomt å kontrollere kommunikasjonen mellom slike tjenester. Den eneste måten å gjøre det her på er å sette tjenester i separate VPC-er, for mye arbeid.

Forsøk 2. Lambda

Hvorfor legger vi ikke bare hver mikroservice i en egen AWS Lambda? Vil dette løse problemet?

Ja, det vil faktisk være en serverløs mikroservice, og du vil kunne bruke IAM-policyer for å innstille tilgangene mellom tjenestene, men ... Det er ikke "lett".

Jeg vet at dette er ganske normalt for tiden å ha en liten funksjon som distribusjonsenhet. Og i tilfelle når tjenesten din har mer enn 1 sluttpunkt / metode / funksjon, anses det som ok å distribuere den som flere Lambdas.

Jeg forstår fordelene med det, men du ofrer enkel vedlikehold og utvikling. Dessuten liker jeg virkelig ikke en ide om å få en tjeneste distribuert som et sett med Lambda-funksjoner. Se for deg flere separate funksjoner som arbeider med fakturering? Det er ikke en avgrenset kontekst lenger. Selv om det er tilfeller der slik granularitet kan være nyttig, men det er et sjeldent tilfelle.

Forsøk 3. Fat Lambda

Kan vi faktisk distribuere et sett med endepunkter som en enkelt Lambda (uten å bruke API Gateway, selvfølgelig)?

Hvis vi kunne gjøre dette, ville vi fått alle fordelene med det forrige alternativet, men vi ville også være i stand til å velge granulariteten til distribusjonsenhetene våre.

Slik jeg vil ha det er følgende: hver distribuerbare tjeneste skal være et enkelt vanlig gammelt JS-objekt med metoder. Dette er ganske trivielt å oppnå ved å legge til noen få linjer limkode mellom objektet ditt og AWS Lambda.

Her er implementeringen av den: aws-rpc. Denne nodejs-modulen eksponerer lambdaHandler-funksjonen, der du bare passerer et objekt, og den blir automatisk eksponert for alle som kan få tilgang til Lambda:

import {lambdaHandler} fra 'aws-rpc';
import {TestServiceImpl} fra './TestServiceImpl';
// dette er distribusjonsenheten din
// dette er hva du spesifiserer som Lambdas behandlingsfunksjon
export const handler = lambdaHandler (ny TestServiceImpl ());

Nå kan du bare distribuere “handler” som AWS Lambda. Slik påkaller du metodene:

import {TestService} fra './TestService';
const client = avvente createClient  ("LambdaName", "test");
console.log (avvente client.test ());

Vær oppmerksom på at for å kunne generere metoder for klientstubobjektet, må du gi alle metodenavnene til createClient, slik vi gjorde i eksemplet.

Dette er påkrevd fordi JS ikke har noen kjøretidsinformasjon om TypeScript-grensesnitt. Jeg kunne implementere det ved å bruke abstrakte klasser, men jeg liker ikke det ¯ \ _ (ツ) _ / ¯.

Bonus! Du kan kjøre alt lokalt!

Jeg tror at det er veldig viktig å ha det lokale utviklingsmiljøet ditt så komfortabelt som mulig. Dette er grunnen til at jeg også har lagt til en mulighet til å kjøre tjenesten og klienten lokalt uten å distribuere noe til AWS (se funksjonene runService og createClient). For eksempler, se depotet på GitHub.

Sammendrag

Dette er veldig enkelt å gå seg vill i tjenestene som nettskydeleverandører tilbyr, og overengineer infrastrukturen din.

Jeg velger alltid den mest enkle og eksplisitte løsningen jeg kan tenke på. Husk også alltid at mange teknikker og fremgangsmåter kan gjenbrukes fra andre plattformer (ideen om fettet NodeJS Lambda er inspirert av såkalte fettkrukker fra Java-verdenen).

Hvis du likte dette emnet, sjekk også ut disse:

  • Du må lære å lage den beste serverløse arkitekturen
  • Hvordan lage gratis serverløs CI / CD-rørledning: 3 enkle eksempler
  • Hvordan enkelt replikere DynamoDB på tvers av regioner
  • Hvordan lage multiregisjonell applikasjon (og betale null)
  • Gjør alle Java Web App Serverløse

Kommentarer, likes og delinger blir høyt verdsatt. Jubel!