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

Я надеюсь, что вы любите Serverless так же сильно, как и я, потому что это еще один пост на эту тему.

Теперь, если мы говорим о простом бессерверном REST API, ваши настройки совершенно очевидны для AWS: Lambda + API Gateway.

Но как насчет других (микро) сервисов, которые может иметь ваш бэкэнд? Знаете, не самая лучшая идея - поместить весь код приложения в одну монолитную лямбда-функцию AWS.

Соревнование

Мы хотим легко развернуть прикладные модули как микросервисы без сервера, которые также должны взаимодействовать друг с другом. Предпочтительно связь между службами должна регулироваться каким-либо ACL.

Попытка 1. API-шлюз

Это первая мысль, которая у меня возникла, когда я пытался решить проблему: просто выставить все микросервисы через API-шлюз. Проблема в том, что ... Созданные API общедоступны.

Почему это проблема? Например, мы не хотим, чтобы биллинговая служба была открыта для всего мира, даже если доступ ограничен каким-либо разрешением.

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

Вы можете использовать политики ресурсов API Gateway, чтобы ваш API мог безопасно вызываться:
* пользователи с указанной учетной записи AWS
* указанные диапазоны IP-адресов источника или блоки CIDR
* указанные виртуальные частные облака (VPC) или конечные точки VPC (в любом аккаунте)

Это делает довольно затруднительным контролировать связь между такими службами. Единственный способ сделать это - поместить службы в отдельные VPC, слишком много работы.

Попытка 2. Лямбда

Почему бы нам просто не поместить каждый микросервис в отдельную AWS Lambda? Это решит проблему?

Да, на самом деле это будет микросервис без сервера, и вы сможете использовать политики IAM для настройки доступа между службами, но ... Это не «просто».

Я знаю, что в настоящее время вполне нормально иметь крошечную функцию в качестве единицы развертывания. А в случае, когда у вашего сервиса более 1 конечной точки / метода / функции, считается целесообразным развернуть его как несколько лямбд.

Я понимаю его преимущества, но вы жертвуете простотой обслуживания и развития. Кроме того, мне не нравится идея развертывания службы в виде набора лямбда-функций. Представляете, несколько отдельных функций, связанных с биллингом? Это больше не ограниченный контекст. Хотя бывают случаи, когда такая детализация может быть полезной, но это редкий случай.

Попытка 3. Жирная лямбда

Можем ли мы на самом деле развернуть набор конечных точек как одну лямбду (конечно, без использования API Gateway)?

Если бы мы могли это сделать, мы бы получили все преимущества предыдущего варианта, но мы также смогли бы выбрать степень детализации наших модулей развертывания.

Я хочу это следующим образом: каждый развертываемый сервис должен быть простым простым старым объектом JS с методами. Этого довольно просто добиться, добавив несколько строк связующего кода между вашим объектом и AWS Lambda.

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

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

Теперь вы можете просто развернуть «обработчик» как AWS Lambda. Вот как вы вызываете его методы:

импортировать {TestService} из './TestService';
const client = await createClient  ("LambdaName", "test");
console.log (ожидайте client.test ());

Обратите внимание, что для того, чтобы иметь возможность генерировать методы для объекта-заглушки клиента, вы должны передать все имена методов в createClient, как мы это делали в примере.

Это необходимо, потому что JS не имеет никакой информации об интерфейсах TypeScript во время выполнения. Я мог бы реализовать это, используя абстрактные классы, но мне это не нравится ¯ \ _ (ツ) _ / ¯.

Бонус! Вы можете запустить все это локально!

Я считаю, что очень важно, чтобы ваша местная среда разработки была максимально комфортной. Вот почему я также добавил возможность локально запускать службу и клиента без развертывания чего-либо в AWS (см. Функции runService и createClient). Для примеров, смотрите репозиторий на GitHub.

Резюме

Это очень легко потерять в услугах, которые предлагают облачные провайдеры, и перегрузить вашу инфраструктуру.

Я всегда выбираю самое простое и понятное решение, которое только можно придумать. Кроме того, всегда помните, что многие методы и практики могут быть повторно использованы с других платформ (идея толстой NodeJS Lambda вдохновлена ​​так называемыми толстыми банками из мира Java).

Если вам понравилась эта тема, проверьте также:

  • Вы должны научиться делать лучшую безсерверную архитектуру
  • Как создать бесплатный серверный конвейер CI / CD: 3 простых примера
  • Как легко реплицировать DynamoDB в разных регионах
  • Как сделать многорегиональное приложение (и заплатить ноль)
  • Сделать любое Java-приложение без сервера

Комментарии, лайки и акции высоко ценятся. Ура!