Машинопись

NestJS: микросервисы с gRPC, шлюзом API и аутентификацией — часть 1/2

Пошаговое руководство: приложения NestJS с TypeScript, gRPC, шлюзом API, аутентификацией и проверкой

Сегодня я хочу познакомить вас с микросервисами в NestJS (TypeScript)в сочетании с инфраструктурой gRPC от Google и API Gateway. для обработки входящих HTTP-запросов и аутентификации на основе JWT. Эта статья получилась очень длинной, поэтому я разделил ее на 2 части.

  1. Введение, подготовка, базы данных, общий прототип проекта
  2. Микросервис аутентификации, Микросервис продукта, Микросервис заказа

Вы найдете ссылку на каждый репозиторий в каждом разделе этой статьи. Вторую часть можно прочитать здесь.

Инфраструктура приложений

Для этой статьи я решил закодировать простой проект микросервиса электронной коммерции с API-шлюзом, который управляет входящими HTTP-запросами и перенаправляет их в микросервисы, которых всего будет 3.

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

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

Мы не будем заниматься переменными окружения, дедлайнами, глубокой обработкой ошибок, докером и сложными конфигурациями. Так что не беспокойтесь, у нас все просто!

Каждая услуга будет самостоятельным проектом, так что имейте это в виду. Кроме того, у нас будет общий репозиторий, в котором мы храним и управляем файлами Proto, что является обычной практикой при работе с gRPC. И последнее, но не менее важное: мы создадим еще один проект, который будет шлюзом API. Итак, мы говорим о 5 проектах всего.

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

Что такое NestJS?

NestJS — это фреймворк для создания эффективных масштабируемых веб-приложений Node.js. Он использует современный JavaScript и построен на TypeScript. Если вы разрабатываете API, созданный с помощью TypeScript, то NestJS — это то, что вам нужно! Он сильно вдохновлен Spring и Angular.

Что такое gRPC?

gRPC — это современная высокопроизводительная RPC-инфраструктура с открытым исходным кодом, которая может работать в любой среде. Он может эффективно подключать службы в центрах обработки данных и между ними с подключаемой поддержкой балансировки нагрузки, трассировки, проверки работоспособности и аутентификации.

Что такое шлюз API?

API-шлюз — это точка входа для всех клиентов, в нашем случае — для всех клиентских запросов на основе HTTP, но не обязательно ограничиваться только HTTP. Шлюз API обрабатывает запросы одним из двух способов. Некоторые запросы просто проксируются/маршрутизируются на соответствующую службу. Он обрабатывает другие запросы, разветвляясь на несколько служб.

Пошаговое руководство

Как я уже сказал, я разделил эту статью на две части. Покрытие будет таким:

  1. Базы данных, Общий прототип проекта, Шлюз API
  2. Микрослужба аутентификации, микрослужба продуктов и микрослужба заказов

Предпосылки

Требуется базовое понимание TypeScript, RPC, Git (+ Github), PostgreSQL, которые вы установили локально на свой компьютер. Я выберу Visual Studio Code в качестве редактора кода. Вы можете использовать все, что вы предпочитаете.

Внимание

В этой статье вы будете часто встречать команду code .. Это команда кода Visual Studio, которая открывает код Visual Studio на основе текущего каталога. Если вы не используете Visual Studio Code, убедитесь, что вы открываете правильный каталог в своей среде IDE или редакторе кода.

База данных

Во-первых, нам нужно создать 3 базы данных PostgreSQL. Это потому, что мы будем следовать шаблону База данных на службу. Каждый отдельный микросервис будет иметь свою базу данных, чтобы быть независимым даже в том, что касается управления данными.

Каждый справляется с этим по-своему, некоторые люди используют какой-то графический интерфейс, но мы собираемся использовать наш терминал. Опять же, на вашем компьютере должен быть установлен PostgreSQL. Если у вас установлен PostgreSQL, следующие четыре команды будут выполняться на компьютерах с Linux, Mac и Windows.

$ psql postgres
$ CREATE DATABASE micro_auth;
$ CREATE DATABASE micro_product;
$ CREATE DATABASE micro_order;
$ \l
$ \q

Командное объяснение:

  • psql postgres открывает интерфейс командной строки psql с пользователем Postgres
  • CREATE DATABASE micro_auth; создание базы данных
  • CREATE DATABASE micro_product; создание базы данных
  • CREATE DATABASE micro_order; создание базы данных
  • \l перечислить все базы данных
  • \q выход из интерфейса командной строки psql

Мой терминал будет выглядеть так после того, как мы успешно выполним все четыре команды. Как мы видим, 3 базы данных были созданы успешно.

Создание проектов

Давайте продолжим с NestJS. Мы собираемся установить NestJS CLI глобально.

$ npm i -g @nestjs/cli

Мы инициализируем 4 новых проекта NestJS с помощью интерфейса командной строки. Кроме того, мы создаем проект для наших прото-файлов, которыми мы собираемся поделиться на Github.

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

$ mkdir grpc-nest-proto
$ nest new grpc-nest-api-gateway -p npm
$ nest new grpc-nest-auth-svc -p npm
$ nest new grpc-nest-product-svc -p npm
$ nest new grpc-nest-order-svc -p npm

Общий репозиторий прототипов

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

Гитхаб: https://github.com/hellokvn/grpc-nest-proto

Во-первых, нам нужно открыть проект в нашем редакторе кода, эта команда code . открывает проект grpc-proto в нашем редакторе VSCode.

$ cd grpc-nest-proto
$ npm init --y
$ git init
$ mkdir proto
$ touch proto/auth.proto && touch proto/product.proto && touch proto/order.proto
$ code .

Проект будет выглядеть так:

Затем мы добавим некоторый код в наши прото-файлы. Следуй за мной.

Авторизация Прото

Во-первых, мы собираемся создать файл Proto для нашей службы аутентификации. Мы добавим 3 конечные точки RPC: Register, Login и Validate.

Давайте добавим немного кода в proto/auth.proto

Заказать Прото

Во-вторых, мы собираемся создать файл Proto для нашей службы заказов. Мы добавим только 1 конечную точку RPC с именем CreateOrder.

Давайте добавим немного кода в proto/order.proto

Прототип продукта

И последнее, но не менее важное: мы собираемся создать файл Proto для нашей службы продукта. Мы добавим 3 конечные точки RPC: CreateProduct, FineOne и DecreaseStock.

Давайте добавим немного кода в proto/product.proto

Создание репозитория на Github

Как я уже сказал, нам нужно как-то поделиться этим проектом. Для этого руководства я выбираю Github. Итак, давайте создадим публичный репозиторий здесь. Кстати, это единственный репозиторий, который вам нужно создать в этом руководстве. Мы установим этот репозиторий как пакет NPM позже в наших проектах.

Давайте вернемся к нашему коду, потому что нам нужно зафиксировать и отправить наш проект.

Замените YOUR_USERNAME своим именем пользователя Github.

$ git remote add origin https://github.com/YOUR_USERNAME/grpc-nest-proto.git
$ git add .
$ git commit -m "chore(): init nestjs"
$ git branch -M main
$ git push -u origin main

Вот и все. Теперь наш код должен быть на Github. Мы больше не будем вносить здесь никаких изменений, давайте перейдем к шлюзу API.

Шлюз API

Репозиторий: https://github.com/hellokvn/grpc-nest-api-gateway

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

Во-первых, нам нужно открыть проект в нашем редакторе кода, поэтому вернитесь в свой терминал в каталог, где мы храним наши проекты.

$ cd grpc-nest-api-gateway
$ code .

Установка зависимостей

Давайте установим некоторые зависимости, которые нам понадобятся.

$ npm i @nestjs/microservices @grpc/grpc-js @grpc/proto-loader
$ npm i -D @types/node ts-proto

Структура проекта

Как обычно в моих руководствах, я продолжу создание окончательной структуры папок и файлов. Для простоты мы просто используем один модуль.

$ nest g mo auth && nest g co auth --no-spec && nest g s auth --no-spec
$ nest g mo product && nest g co product --no-spec
$ nest g mo order && nest g co order --no-spec
$ touch src/auth/auth.guard.ts

Добавление скриптов

Нам нужно добавить несколько скриптов в наш package.json для создания файлов protobuf на основе общего проекта proto, который мы только что завершили.

Давайте просто добавим эти 5 строк кода в свойство scripts нашего файла package.json.

Замените YOUR_USERNAME своим именем пользователя Github.

Вот так он будет выглядеть на моем package.json или проверить этот файл в моем репозитории.

Давайте запустим эти скрипты!

$ npm run proto:install && npm run proto:all
  • proto:install установит наш общий прото-репозиторий как пакет NPM.
  • proto:all создаст наши файлы protobuf с суффиксом .pb.ts внутри наших модулей: auth, order и product

Итак, после этих шагов проект должен выглядеть так:

Теперь давайте начнем кодировать.

АутСервис

Итак, что мы собираемся сделать здесь, так это заставить нашу службу аутентификации вызывать метод проверки, который мы собираемся закодировать позже. Но мы уже можем его подготовить, так как у нас есть его файл protobuf. Мы знаем его ответ и полезную нагрузку.

Давайте изменим src/auth/auth.service.ts с

to

Защита авторизации

Наш AuthGuard зависит от службы, которую мы только что создали. Здесь мы получаем Bearer Token, который мы собираемся получить позже. Затем мы проверяем этот токен, если он недействителен, мы выбрасываем неавторизованное исключение, поэтому мы блокируем запрос для пользователей без действительной авторизации.

Давайте изменим src/auth/auth.guard.ts с

Контроллер авторизации

Микрослужба аутентификации также позаботится о новых пользователях и входах пользователей в систему, поэтому мы также добавляем контроллер в наш шлюз API для пересылки этих запросов в нашу микрослужбу аутентификации.

Давайте изменим src/auth/auth.controller.ts с:

to

Модуль авторизации

Теперь нам нужно зарегистрировать нашу службу аутентификации. Нам нужно будет сделать этот модуль глобальным и экспортировать наш AuthService, потому что нам нужно использовать AuthGuard, который зависит от AuthService, внутри наших других модулей. Так что имейте это в виду.

Давайте изменим src/auth/auth.module.ts файл

to

Теперь мы закончили с модулем аутентификации нашего шлюза API. Продолжим работу с модулем заказа. Это намного проще, чем наш модуль авторизации.

Модуль заказа

Как и в случае с нашим модулем AuthModule, нам необходимо зарегистрировать наш микросервис Order, чтобы позже связываться с ним.

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

Давайте изменим src/order/order.module.ts форму

to

Контроллер заказов

Здесь нам нужно закодировать только одну конечную точку, потому что наша микрослужба заказов владеет только одной конечной точкой. Взгляните, мы собираемся использовать нашу службу AuthGuard здесь, чтобы проверить авторизацию этого запроса POST, который мы собираемся кодировать сейчас.

Если пользователь, который делает этот запрос, авторизован, AuthGuard добавляет идентификатор пользователя к запросу, который мы собираемся здесь объединить с телом запроса, поскольку для нашего файла protobuf order.pb.ts требуется идентификатор пользователя.

Давайте изменим src/order/order.controller.ts форму

to

Модуль продукта

Теперь давайте повторим этот процесс для нашего модуля продукта нашего шлюза API.

Давайте изменим src/product/product.module.ts с

to

Контроллер продукта

Микросервис продукта содержит 3 конечные точки, но DecreaseStock не должен быть доступен из нашего шлюза API, поэтому мы просто добавим две другие конечные точки.

Давайте изменим src/product/product.controller.ts форму

to

Большой! Вот и все. Шлюз API завершен. Теперь мы можем запустить его. К сожалению, этот API-шлюз бесполезен без своих микросервисов, поэтому давайте продолжим вторую часть этой статьи.

$ npm run start:dev

Спасибо, что прочитали первую часть моей статьи о микросервисах с NestJS. Нажмите здесь, чтобы перейти к части 2.

Ваше здоровье!

Надеюсь, вам понравилось это читать. Если вы хотите поддержать меня как писателя, рассмотрите возможность подписки стать участником Medium. Всего 5 долларов в месяц, и вы получаете неограниченный доступ к Medium.

Хотите поддержать меня? Купи мне кофе.

Читать дальше



Повышение уровня кодирования

Спасибо, что являетесь частью нашего сообщества! Нанимайте лучших инженеров-программистов на Платформе вакансий Level Up.