Как да направите всеки NodeJS приложение без сървър

Надявам се да обичате Serverless толкова много, колкото и аз, защото това е още един пост по тази тема.

Сега, ако говорим за прост REST API без сървър, настройката ви е съвсем очевидна за AWS: Lambda + API Gateway.

Но какво ще кажете за други (микро) услуги, които вашият бекенд може да има? Знаете, не е най-добрата идея да поставите целия си код на приложение в една монолитна функция AWS Lambda.

Предизвикателството

Искаме лесно да разгърнем приложни модули като безсерверни микросервизи, които също трябва да комуникират помежду си. За предпочитане комуникацията между услугите трябва да се регулира от някакъв вид ACL.

Опит 1. API шлюз

Това е първата мисъл, която имах, когато се опитвах да реша проблема: просто изложи всички микросервизи чрез Gateway API. Проблемът е ... Създадените API-та са публични.

Защо това е проблем? Например, не искаме да имаме услуга за фактуриране, която да бъде изложена на целия свят, дори ако достъпът е ограничен с помощта на някакво разрешение.

Е, можете да направите API частен, но политиките за сигурност са доста ограничени:

Можете да използвате правилата за ресурсите на шлюза на API, за да позволите на вашия API да бъде надеждно извикан от:
* потребители от посочен AWS акаунт
* посочени диапазони на IP адрес на източник или CIDR блокове
* посочени виртуални частни облаци (VPC) или крайни точки VPC (във всеки акаунт)

Това прави доста неприятно да се контролира комуникацията между такива услуги. Единственият начин да го направите тук е чрез поставяне на услуги в отделни VPC, твърде много работа.

Опит 2. Ламбда

Защо просто не поставим всяка микрослужба в отделна AWS Lambda? Това ще реши ли проблема?

Да, всъщност това ще бъде микросервиз без сървър и ще можете да използвате политиките на IAM, за да настроите достъпа между услугите, но ... Това не е „лесно“.

Знам, че в днешно време това е съвсем нормално да има малка функция като вашето устройство за разполагане. И в случай, че вашата услуга има повече от 1 крайна точка / метод / функция, ще се счита за добре да я разгърнете като множество лямбда.

Разбирам предимствата на него, но вие жертвате лекотата на поддръжка и развитие. Освен това наистина не ми харесва идеята да има услуга, разгърната като набор от функции на Lambda. Представете си, няколко отделни функции, занимаващи се с таксуването? Това вече не е ограничен контекст Въпреки че има случаи, при които подобна подробност може да бъде полезна, но това е рядък случай.

Опит 3. Дебела ламбда

Можем ли всъщност да разположим набор от крайни точки като една Lambda (без да използваме API Gateway, разбира се)?

Ако можехме да направим това, щяхме да извлечем всички предимства на предишния вариант, но също така щяхме да можем да изберем подробността на нашите звена за разполагане.

Начинът, по който искам е следният: всяка разгъваема услуга трябва да е обикновен обикновен стар JS обект с методи. Това е доста тривиално за постигане, като добавите няколко реда код на лепило между вашия обект и AWS Lambda.

Ето моята реализация на това: aws-rpc. Този модул nodejs излага функция lambdaHandler, при която просто предавате обект, и той е автоматично изложен на всеки, който има достъп до Lambda:

import {lambdaHandler} от 'aws-rpc';
import {TestServiceImpl} от './TestServiceImpl';
// това е вашето звено за разполагане
// това е, което определяте като функция за обработка на Lambda
експортиране на const handler = lambdaHandler (нов TestServiceImpl ());

Сега можете просто да разгърнете „манипулатора“ като AWS Lambda. Ето как се позовавате на неговите методи:

import {TestService} от './TestService';
const client = изчакайте createClient  ("LambdaName", "test");
console.log (чакайте client.test ());

Моля, обърнете внимание, че за да можете да генерирате методи за обекта на клиента, трябва да предадете всички имена на методи за createClient, както направихме в примера.

Това е необходимо, тъй като JS няма никаква информация по време на работа за TypeScript интерфейси. Бих могъл да го реализирам с помощта на абстрактни класове, но не ми харесва ¯ \ _ (ツ) _ / ¯.

Бонус! Можете да го стартирате на локално ниво!

Вярвам, че е много важно вашата местна среда за развитие да бъде максимално удобна. Ето защо добавих и възможност за стартиране на услугата и клиент на местно ниво, без да разгръщам нищо в AWS (вижте функциите runService и createClient). За примери вижте хранилището в GitHub.

резюме

Това е много лесно да се загубите в услугите, които предлагат облачните доставчици, и да пренастроите вашата инфраструктура.

Винаги избирам най-простото и ясно решение, за което мога да се сетя. Също така, винаги помнете, че много техники и практики могат да бъдат използвани повторно от други платформи (идеята за тлъстия NodeJS Lambda е вдъхновена от така наречените мазнини буркани от света на Java).

Ако тази тема ви е харесала, разгледайте и тях:

  • Трябва да научите как да направите най-добрата без сървър архитектура
  • Как да създадете безплатен CI / CD тръбопровод без сървър: 3 лесни примера
  • Как лесно да копирате DynamoDB в регионите
  • Как да направите многорегионално приложение (и плащане нула)
  • Направете всеки Java Web App Server без сървър

Коментари, харесвания и споделяния са високо оценени. Наздраве!