Paano gumawa ng isang NodeJS app serverless

Inaasahan kong mahal mo ang Serverless tulad ng pag-ibig ko dahil ito ay isa pang post sa paksa.

Kung ito ay isang simpleng REST API na walang server, ang iyong pag-set up sa AWS: Lambda + API Gateway ay halata.

Ngunit paano ang iba pang (micro) na mga serbisyo na maaaring mayroon ang iyong backend? Alam mo, ang paglalagay ng lahat ng iyong code ng aplikasyon sa isang solong monolitik AWS Lambda function ay hindi ang pinakamahusay na ideya.

Ang hamon

Nais naming magbigay ng mga module ng aplikasyon bilang simpleng mga server na walang microservices na kailangan ding makipag-usap sa bawat isa. Ang komunikasyon sa pagitan ng mga serbisyo ay dapat na mas mabuti na makontrol ng isang uri ng ACL.

Pagtatangka 1. API Gateway

Ito ang unang naisip ko noong sinusubukang lutasin ang problema: ilantad lamang ang lahat ng mga microservices sa pamamagitan ng API Gateway. Ang problema ay ... ang mga API na nalilikha ay pampubliko.

Bakit problema iyan? Halimbawa, hindi namin nais ang isang serbisyo sa pagsingil na magamit sa buong mundo kahit na ang pag-access ay pinaghihigpitan ng pahintulot.

Kaya, maaari mong gawing pribado ang API, ngunit ang mga alituntunin sa seguridad ay medyo limitado:

Maaari mong gamitin ang Mga Patakaran sa Mapagkukunan ng API Gateway upang payagan ang iyong API na ligtas na maimbitahan ng:
* Gumagamit ng isang tukoy na AWS account * Mga tinukoy na saklaw ng mga address ng IP address o mga bloke ng CIDR * Mga tinukoy na virtual na pribadong cloud (VPC) o mga endpoint ng VPC (sa anumang account)

Ginagawa nitong mahirap upang makontrol ang komunikasyon sa pagitan ng mga nasabing serbisyo. Ang tanging paraan lamang upang magawa ito dito ay ang maglagay ng mga serbisyo sa magkakahiwalay na VPC, na labis na trabaho.

Eksperimento 2. Lambda

Bakit hindi nalang natin ilagay ang bawat microservice sa isang hiwalay na AWS Lambda? Malulutas ba nito ang problema?

Oo, ito ay talagang isang walang server na microservice, at maaari mong gamitin ang mga patakaran ng IAM upang i-optimize ang inter-service access. Gayunpaman, ito ay hindi "madali".

Alam ko na medyo normal sa mga araw na ito na magkaroon ng isang maliit na papel bilang isang yunit ng paghahatid. Sa kaganapan na ang iyong serbisyo ay may higit sa isang endpoint / pamamaraan / pagpapaandar, mainam na ibigay ito bilang maraming lambdas.

Naiintindihan ko ang mga pakinabang, ngunit isinakripisyo mo ang kadalian ng pagpapanatili at pag-unlad. Gayundin, hindi ko talaga gusto ang ideya ng pagkakaroon ng isang serbisyo na nakalantad bilang isang hanay ng mga pag-andar ng Lambda. Mag-isip ng maraming magkakahiwalay na pagpapaandar na nakikipag-usap sa pagsingil? Hindi na ito isang limitadong konteksto. Habang may mga kaso kung saan maaaring maging kapaki-pakinabang ang naturang granularity, ito ay isang bihirang kaso.

Subukan 3. Matabang Lambda

Maaari ba talaga kaming magbigay ng isang bilang ng mga endpoint bilang isang solong Lambda (walang kurso sa API, syempre)?

Kung magagawa natin ito ay susulitin natin ang nakaraang pagpipilian, ngunit maaari din naming piliin ang granularity ng aming mga yunit ng paglawak.

Narito kung ano ang gusto ko: Ang anumang serbisyo na maaari mong ipatupad ay dapat na isang simple, lumang JS object na may mga pamamaraan. Ito ay medyo madali upang magawa sa pamamagitan ng pagdaragdag ng ilang mga linya ng glue code sa pagitan ng iyong object at AWS Lambda.

Narito ang aking pagpapatupad nito: aws-rpc. Inilantad ng modyul na nodejs ang pagpapaandar ng lambdaHandler kung saan ipapasa mo lamang ang isang bagay, at awtomatiko itong ginawang magagamit sa lahat ng mga gumagamit na maaaring ma-access ang lambda:

i-import ang {lambdaHandler} mula sa 'aws-rpc'; I-import ang {TestServiceImpl} mula sa './TestServiceImpl';
// this is your staging unit // ito ang iyong tinukoy bilang lambda handler function export const handler = lambdaHandler (bagong TestServiceImpl ());

Ngayon ay maaari mo lamang ibigay ang "handler" bilang AWS Lambda. Paano tawagan ang mga pamamaraan:

I-import ang {TestService} mula sa './TestService';
Const client = maghintay para sa createClient ("LambdaName", "test"); console.log (hintayin ang client.test ());

Mangyaring tandaan na upang makabuo ng mga pamamaraan para sa object ng client client, dapat mong ipasa ang lahat ng mga pangalan ng pamamaraan upang likhain ang Kliyente tulad ng halimbawa.

Ito ay kinakailangan dahil ang JS ay walang impormasyon sa runtime tungkol sa mga interface ng TypeScript. Maaari kong ipatupad ito sa mga abstract na klase, ngunit hindi ko gusto ang \ _ (ツ) _ /Ā.

Bonus! Maaari mong gawin ang lahat nang lokal!

Sa palagay ko napakahalaga na ang iyong lokal na kapaligiran sa pag-unlad ay komportable hangga't maaari. Para sa kadahilanang ito, nagdagdag din ako ng kakayahang patakbuhin ang serbisyo at client nang lokal nang hindi kinakailangang magbigay ng anuman para sa AWS (tingnan ang mga pagpapaandar na runService at createClient). Maaari kang makahanap ng mga halimbawa sa repository ng GitHub.

Buod

Napakadaling gawin kapag nawala ka sa mga serbisyong inaalok ng cloud provider at maingat na pagsusuri ng iyong imprastraktura.

Palagi kong pinipili ang pinakasimpleng at pinaka-malinaw na solusyon na naiisip ko. Gayundin, laging tandaan na maraming mga diskarte at kasanayan ang maaaring magamit muli mula sa iba pang mga platform (ang ideya ng naka-bold na NodeJS Lambda ay inspirasyon ng tinatawag na naka-bold na baso mula sa mundo ng Java).

Kung nagustuhan mo ang paksang ito, basahin din ang sumusunod:

  • Kailangan mong malaman kung paano bumuo ng pinakamahusay na arkitektura na walang server
  • Paano Bumuo ng isang Libreng Serverless CI / CD Pipeline: 3 Mga Simpleng Halimbawa
  • Madaling pagtitiklop ng DynamoDB sa mga rehiyon
  • Paano Bumuo ng isang Multi-Regional Application (at Pay Zero)
  • Gawin ang Java Web App Serverless

Ang mga komento, gusto at pagbabahagi ay labis na pinahahalagahan. Ibaba!