Cum să faci orice aplicație NodeJS fără server

Sper să-ți placă Serverless la fel de mult ca mine, deoarece aceasta este încă o postare pe acest subiect.

Acum, dacă vorbim despre o simplă API REST fără server, configurarea dvs. este destul de evidentă pe AWS: Lambda + API Gateway.

Dar ce zici de alte (micro) servicii pe care le poate avea backend-ul dvs.? Știți, nu este cea mai bună idee să puneți tot codul aplicației într-o singură funcție monolitică AWS Lambda.

Provocarea

Vrem să implementăm cu ușurință module de aplicație ca microservicii fără server, care trebuie să comunice și ele. De preferință, comunicarea între servicii ar trebui reglementată de un fel de ACL.

Încercare 1. Gateway API

Acesta este primul gând pe care l-am avut când încercam să rezolv problema: doar expun toate microserviciile prin API Gateway. Problema este ... API-urile create sunt publice.

De ce este o problemă? De exemplu, nu dorim să avem un serviciu de facturare care să fie expus întregii lumi, chiar dacă accesul este restricționat folosind un fel de autorizare.

Puteți face ca API-ul să fie privat, dar politicile de securitate sunt destul de limitate:

Puteți utiliza politicile de resurse API Gateway pentru a permite API-ului dvs. să fie invocat în siguranță de:
* utilizatori dintr-un cont AWS specificat
* domenii de adresă IP sursă specificate sau blocuri CIDR
* noruri private virtuale specificate (VPC) sau puncte finale VPC (în orice cont)

Acest lucru face destul de dificil să controlați comunicațiile între astfel de servicii. Singurul mod de a face acest lucru este prin introducerea serviciilor în VPC-uri separate, prea multă muncă.

Încercare 2. Lambda

De ce nu introducem fiecare microserviciu într-un lambda separat AWS? Acest lucru va rezolva problema?

Da, de fapt, va fi un microserviciu fără server și veți putea utiliza politicile IAM pentru a ajusta accesele între servicii, dar ... Nu este „ușor”.

Știu că în zilele noastre este destul de normal să ai o funcție minusculă ca unitate de implementare. Și în cazul în care serviciul dvs. are mai mult de 1 punct final / metodă / funcție, este considerat bine să îl implementați ca mai multe Lambdas.

Înțeleg avantajele acesteia, dar sacrifici ușurința de întreținere și dezvoltare. De asemenea, chiar nu îmi place o idee de a avea un serviciu implementat ca un set de funcții Lambda. Imaginați-vă, mai multe funcții separate care se ocupă de facturare? Nu mai este un context delimitat. Deși există cazuri în care o asemenea granularitate poate fi utilă, dar este un caz rar.

Încercare 3. Fat Lambda

Putem implementa de fapt un set de puncte ca un Lambda unic (fără a utiliza API Gateway, desigur)?

Dacă am putea face acest lucru, am obține toate avantajele opțiunii anterioare, dar am putea alege, de asemenea, granularitatea unităților noastre de implementare.

Modul în care vreau este următorul: fiecare serviciu implementabil ar trebui să fie un simplu obiect JS simplu simplu cu metode. Acest lucru este destul de banal pentru a obține adăugând câteva linii de cod de adeziv între obiectul tău și Lambda AWS.

Iată implementarea mea: aws-rpc. Acest modul nodejs expune funcția lambdaHandler, unde treceți doar un obiect și este expus automat oricui este capabil să acceseze Lambda:

import {lambdaHandler} din 'aws-rpc';
importați {TestServiceImpl} din „./TestServiceImpl”;
// aceasta este unitatea dvs. de implementare
// aceasta este ceea ce specificați ca funcție de handler Lambda
export const handler = lambdaHandler (nou TestServiceImpl ());

Acum, puteți să implementați doar „handler” ca AWS Lambda. Iată cum invocați metodele sale:

importați {TestService} din „./TestService”;
const client = aștepta createClient  ("LambdaName", "test");
console.log (așteptați client.test ());

Vă rugăm să rețineți că, pentru a putea genera metode pentru obiectul stub al clientului, trebuie să treceți toate numele metodelor pentru a creaClient, așa cum am făcut în exemplu.

Acest lucru este necesar deoarece JS nu are nicio informație de rulare despre interfețele TypeScript. L-aș putea implementa folosind clase abstracte, dar nu îmi place ¯ \ _ (ツ) _ / ¯.

Primă! Puteți rula totul local!

Cred că este foarte important să aveți mediul dvs. de dezvoltare locală cât mai confortabil. Acesta este motivul pentru care am adăugat, de asemenea, o capacitate de a rula serviciul și clientul local, fără a implementa nimic în AWS (consultați funcțiile runService și createClient). Pentru exemple, consultați depozitul de pe GitHub.

rezumat

Acest lucru este foarte ușor să vă pierdeți în serviciile oferite de furnizorii de cloud și să vă consolidați infrastructura.

Aleg întotdeauna cea mai simplă și explicită soluție la care mă pot gândi. De asemenea, amintiți-vă întotdeauna că multe tehnici și practici pot fi reutilizate din alte platforme (ideea NodeJS Lambda grasă este inspirată de așa-numitele borcane de grăsime din lumea Java).

Dacă v-a plăcut acest subiect, verificați și acestea:

  • Trebuie să înveți cum să faci cea mai bună arhitectură fără server
  • Cum să creezi conductă CI / CD gratuit fără server: 3 exemple simple
  • Cum să reproduceți cu ușurință DynamoDB în regiuni
  • Cum să faceți o aplicație multiregională (și să plătiți zero)
  • Faceți orice aplicație Java Java fără server

Comentariile, like-urile și share-urile sunt foarte apreciate. Noroc!