Jak zrobić dowolną aplikację NodeJS bez serwera

Mam nadzieję, że kochasz Serverless tak samo jak ja, ponieważ jest to kolejny post na ten temat.

Teraz, gdy mówimy o prostym bezserwerowym interfejsie API REST, twoja konfiguracja jest dość oczywista w AWS: Lambda + API Gateway.

Ale co z innymi (mikro) usługami, które może mieć twój backend? Wiesz, nie jest najlepszym pomysłem umieszczenie całego kodu aplikacji w jednej monolitycznej funkcji Lambda AWS.

Wyzwanie

Chcemy łatwo wdrażać moduły aplikacji jako mikrousługi bezserwerowe, które również muszą się ze sobą komunikować. Najlepiej, aby komunikacja między usługami była regulowana przez pewien rodzaj ACL.

Próba 1. API Gateway

To pierwsza myśl, którą miałem, kiedy próbowałem rozwiązać problem: po prostu ujawnij wszystkie mikrousług za pośrednictwem API Gateway. Problem polega na… Utworzone interfejsy API są publiczne.

Dlaczego to jest problem? Na przykład nie chcemy, aby usługa rozliczeniowa była dostępna dla całego świata, nawet jeśli dostęp jest ograniczony za pomocą autoryzacji.

Możesz ustawić API jako prywatny, ale zasady bezpieczeństwa są dość ograniczone:

Można użyć zasad zasobów API Gateway, aby umożliwić bezpieczne wywoływanie interfejsu API przez:
* użytkownicy z określonego konta AWS
* określone zakresy adresów IP źródłowych lub bloki CIDR
* określone wirtualne chmury prywatne (VPC) lub punkty końcowe VPC (na dowolnym koncie)

Utrudnia to kontrolę komunikacji między takimi usługami. Jedynym sposobem na zrobienie tego jest umieszczenie usług w osobnych VPC, zbyt wiele pracy.

Próba 2. Lambda

Dlaczego nie umieścimy każdej mikrousługi w osobnej AWS Lambda? Czy to rozwiąże problem?

Tak, w rzeczywistości będzie to mikrousługa bezserwerowa i będziesz mógł używać zasad IAM do dostrojenia dostępu między usługami, ale… To nie jest „łatwe”.

Wiem, że w dzisiejszych czasach jest to całkiem normalne, że ma małą funkcję jako jednostka wdrażająca. A w przypadku, gdy twoja usługa ma więcej niż 1 punkt końcowy / metodę / funkcję, rozważa się wdrożenie jej jako wielu Lambdas.

Rozumiem jego zalety, ale poświęcasz łatwość konserwacji i rozwoju. Poza tym nie podoba mi się pomysł wdrożenia usługi jako zestawu funkcji Lambda. Wyobraź sobie kilka oddzielnych funkcji związanych z fakturowaniem? To już nie jest ograniczony kontekst. Chociaż są przypadki, w których taka szczegółowość może być przydatna, ale jest to rzadki przypadek.

Próba 3. Tłuszcz Lambda

Czy faktycznie możemy wdrożyć zestaw punktów końcowych jako pojedynczą Lambdę (oczywiście bez korzystania z API Gateway)?

Gdybyśmy mogli to zrobić, uzyskalibyśmy wszystkie zalety poprzedniej opcji, ale moglibyśmy również wybrać stopień szczegółowości naszych jednostek wdrożeniowych.

Chcę tego, co następuje: każda usługa do wdrożenia powinna być prostym, starym, prostym obiektem JS z metodami. Jest to dość trywialne do osiągnięcia przez dodanie kilku linii kodu kleju między twoim obiektem a AWS Lambda.

Oto moja implementacja: aws-rpc. Ten moduł nodejs ujawnia funkcję lambdaHandler, w której po prostu mijasz obiekt, i jest automatycznie eksponowany dla każdego, kto jest w stanie uzyskać dostęp do Lambda:

import {lambdaHandler} z 'aws-rpc';
import {TestServiceImpl} z './TestServiceImpl';
// to twoja jednostka wdrożeniowa
// to jest to, co określasz jako funkcję handlera Lambdy
export const handler = lambdaHandler (new TestServiceImpl ());

Teraz możesz po prostu wdrożyć „moduł obsługi” jako AWS Lambda. Oto jak wywołujesz jego metody:

import {TestService} z './TestService';
const client = czekaj na createClient  („LambdaName”, „test”);
console.log (czekaj na client.test ());

Pamiętaj, że aby móc wygenerować metody dla obiektu pośredniczącego klienta, musisz przekazać wszystkie nazwy metod do createClient, tak jak to zrobiliśmy w tym przykładzie.

Jest to wymagane, ponieważ JS nie ma żadnych informacji o środowisku wykonawczym na temat interfejsów TypeScript. Mógłbym to zaimplementować za pomocą klas abstrakcyjnych, ale mi się nie podoba ¯ \ _ (ツ) _ / ¯.

Premia! Możesz uruchomić to wszystko lokalnie!

Uważam, że bardzo ważne jest, aby lokalne środowisko programistyczne było jak najbardziej komfortowe. Właśnie dlatego dodałem możliwość lokalnego uruchamiania usługi i klienta bez wdrażania niczego w AWS (zobacz funkcje runService i createClient). Przykłady można znaleźć w repozytorium na GitHub.

Podsumowanie

Bardzo łatwo jest zgubić się w usługach, które oferują dostawcy usług w chmurze i prześcignąć swoją infrastrukturę.

Zawsze wybieram najprostsze i jednoznaczne rozwiązanie, jakie mogę wymyślić. Zawsze też pamiętaj, że wiele technik i praktyk można ponownie wykorzystać z innych platform (idea grubego NodeJS Lambda jest inspirowana tak zwanymi grubymi słoikami ze świata Java).

Jeśli podobał Ci się ten temat, sprawdź również:

  • Musisz nauczyć się tworzyć najlepszą architekturę bezserwerową
  • Jak stworzyć darmowy bezserwerowy potok CI / CD: 3 proste przykłady
  • Jak łatwo replikować DynamoDB między regionami
  • Jak zrobić aplikację wieloregionalną (i Pay Zero)
  • Uczyń dowolną aplikację Java Web Server bez serwera

Komentarze, polubienia i udostępnienia są bardzo mile widziane. Twoje zdrowie!