Создание 3 микросервисов и 1 шлюза API в Go (2022 г.)

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

Эта статья будет разделена на 2 части. Нажмите здесь, чтобы перейти к части 2.

Что будем строить?

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

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

Этот цикл статей состоит из 2 частей:

  1. API Gateway: обрабатывает входящие HTTP-запросы.
  2. Служба аутентификации:предоставляет такие функции, как Регистрация, Вход в систему и генерирует токен с помощью JWT.
  3. Обслуживание товаров. Предоставляет такие функции, как Добавить товар, Уменьшить запас и Найти товар.
  4. Служба заказа. Единственная функция, которую мы предоставляем в этой микрослужбе, — это Создать заказ.

Каждый микросервис будет самостоятельным проектом.

Поскольку эта серия статей уже требует много времени для чтения, я хочу, чтобы эти микросервисы были простыми. Поэтому мы не будем иметь дело с Docker, Deadlines или Timeouts.

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

Давайте начнем!

Создание баз данных

$ psql postgres
$ CREATE DATABASE auth_svc;
$ CREATE DATABASE order_svc;
$ CREATE DATABASE product_svc;
$ \l
$ \q

Вот как должно выглядеть \l. Как видите, мы создали 3 базы данных.

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

Прежде всего, нам нужно создать наши проекты. Я рекомендую создать каталог рабочей области, в котором вы будете хранить свои проекты Go. Входной каталог зависит от вас.

$ mkdir go-grpc-project
$ cd go-grpc-project
$ mkdir go-grpc-api-gateway go-grpc-auth-svc go-grpc-order-svc go-grpc-product-svc

Мы начнем с шлюза API.

$ cd go-grpc-api-gateway

Шлюз API

Гитхаб: https://github.com/hellokvn/go-grpc-api-gateway

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

Инициализировать проект

$ go mod init github.com/YOUR_USERNAME/go-grpc-api-gateway

Установка модулей

$ go get github.com/gin-gonic/gin
$ go get github.com/spf13/viper
$ go get google.golang.org/grpc

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

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

Папки

$ mkdir -p cmd pkg/config/envs pkg/auth/pb pkg/auth/routes pkg/order/pb pkg/order/routes pkg/product/pb pkg/product/routes

Файлы

$ touch Makefile cmd/main.go pkg/config/envs/dev.env pkg/config/config.go
$ touch pkg/auth/pb/auth.proto pkg/auth/routes/login.go pkg/auth/routes/register.go pkg/auth/client.go pkg/auth/middleware.go pkg/auth/routes.go
$ touch pkg/product/pb/product.proto pkg/product/routes/create_product.go pkg/product/routes/find_one.go pkg/product/client.go pkg/product/routes.go
$ touch pkg/order/pb/order.proto pkg/order/routes/create_order.go pkg/order/client.go pkg/product/routes.go

Теперь структура проекта должна выглядеть следующим образом:

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

Файлы Protobuf

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

Прото для аутентификации микросервиса

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

  • регистр
  • Авторизоваться
  • Проверить (веб-токен JSON)

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

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

Микросервис заказа будет обрабатывать только одну задачу — создать заказ. Для этого мы ожидаем идентификатор продукта (мы получим его позже), количество и идентификатор пользователя.

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

Прототип для продуктового микросервиса

Подготовка к взаимодействию с микросервисом заказов завершена, теперь нужно сделать то же самое для микросервиса продуктов.

Прото файл

На этот раз мы ожидаем три конечных точки

  • Создать продукт
  • Найдите один продукт
  • Уменьшить запас продукта

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

Makefile

Далее мы касаемся Makefile. Здесь мы добавляем две команды для выполнения других команд. Может показаться странным, но это, так сказать, ярлык.

Поэтому вместо того, чтобы каждый раз вводить protoc pkg/**…, мы вводим вместо этого make proto.

Давайте добавим код в Makefile

Теперь мы можем сгенерировать файлы protobuf на основе только что созданных файлов proto.

$ make proto

Вывод в консоли должен быть довольно простым:

Файлы protobuf будут создаваться рядом с каждым файлом .proto. Так:

Переменные среды

Нам нужно определить некоторые переменные среды.

Давайте добавим код в pkg/config/envs/dev.env

Конфигурация

В этом файле мы извлекаем данные из нашего файла среды в наш шлюз API.

Давайте добавим код в pkg/config/config.go

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

Конечные точки для микрослужбы проверки подлинности

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

Регистрация Маршрут

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

Итак, что здесь происходит, так это то, что мы создаем структуру, которая называется RegisterRequestBody, где мы привязываем тело HTTP-запроса, которое затем мы привязываем к телу запроса gRPC, который мы собираемся сделать.

Давайте добавим код в pkg/auth/routes/register.go

Осторожно! В большинстве файлов Go вам нужно заменить имя проекта на имя вашего проекта. Здесь вы можете увидеть в строке 8 имя моего модуля. Замените его.

Логин Маршрут

Маршрут входа очень похож на маршрут регистрации. Сначала мы привязываем тело HTTP-запроса, затем отправляем это тело в микросервис аутентификации.

Ответом микросервиса будет веб-токен JSON, этот токен необходим для других маршрутов, которые мы скоро будем кодировать.

Давайте добавим код в pkg/auth/routes/login.go

Клиент микрослужбы аутентификации

Чтобы связаться с микросервисом аутентификации, нам нужно набрать его. Помните, что мы храним URL-адрес этого микросервиса в нашем файле среды, который мы инициализировали с помощью файла config.go. Теперь у нас есть доступ к этим данным.

Давайте добавим код в pkg/auth/client.go

ПО промежуточного слоя аутентификации

Нам необходимо защитить Микросервис Продукта и Заказа от несанкционированных запросов. Это означает, что на некоторых маршрутах мы разрешаем обращаться к нашим защищенным микросервисам только вошедшим в систему пользователям.

То, что мы здесь делаем, проще, чем может показаться. Мы получаем веб-токен JSON из заголовка HTTP-запроса, а затем проверяем этот токен с помощью микрослужбы проверки подлинности. Помните, ранее мы определили конечную точку validate в файле auth.proto.

Если токен проверен, мы пропустим запрос. Если нет, мы выдадим неавторизованную ошибку HTTP.

Давайте добавим код в pkg/auth/middleware.go

Инициализировать маршруты

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

Давайте добавим код в pkg/auth/routes.go

Конечные точки для микросервиса Order

Итак, теперь нам нужно сделать то же самое для микросервиса заказов.

Создать маршрут заказа

Этот маршрут снова похож на маршрут регистрации и входа в систему, который мы закодировали ранее. Получите тело HTTP-запроса и перешлите эти данные в микросервис заказа.

Давайте добавим код в pkg/order/routes/create_order.go

Заказать клиент микросервиса

У микросервиса заказов также должен быть клиент.

Давайте добавим код в pkg/order/client.go

Инициализировать маршруты

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

Давайте добавим код в pkg/order/routes.go

Конечные точки для продуктового микросервиса

Создать маршрут продукта

Этот маршрут также похож на предыдущие маршруты.

Давайте добавим код в pkg/product/routes/create_product.go

Найдите один маршрут

Это первый раз, когда мы получаем параметр маршрута. Мы очень скоро определим этот параметр в URL. Но здесь мы получаем этот параметр с именем id, который затем будет преобразован из строки в целое число, потому что мы определили его как целое число внутри product.proto.

Давайте добавим код в pkg/product/routes/find_one.go

Итак, чего мы не делаем, так это создания маршрута для конечной точки DecreaseStock, которую мы определили в файле product.proto. Это связано с тем, что эта конечная точка не будет напрямую доступна из шлюза API. Мы можем получить доступ к этой конкретной конечной точке только из микросервиса Order, код которого мы напишем во второй части этой серии статей.

Клиент микросервиса продукта

Опять же, нам нужно определить клиента для связи с микрослужбой продукта.

Давайте добавим код в pkg/product/client.go

Инициализировать маршруты

И снова нам нужно зарегистрировать только что созданные маршруты.

Давайте добавим код в pkg/product/register.go

Основной файл

И последнее, но не менее важное: нам нужно загрузить приложение. Помните, мы зарегистрировали маршруты, поэтому теперь нам нужно вызывать эти регистры при запуске приложения.

Давайте добавим код в cmd/main.go

Вот и все! Шлюз API готов!

$ make server

Вывод в терминале должен быть примерно таким:

Продолжим с первым микросервисом.

Микросервис аутентификации (go-grpc-auth-svc)

Гитхаб: https://github.com/hellokvn/go-grpc-auth-svc

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

Пожалуйста, перейдите на go-grpc-auth-svc внутри вашего терминала!

Инициализировать проект

$ go mod init github.com/YOUR_USERNAME/go-grpc-auth-svc

Установка модулей

$ go get github.com/spf13/viper
$ go get google.golang.org/grpc
$ go get gorm.io/gorm
$ go get gorm.io/driver/postgres
$ go get golang.org/x/crypto/bcrypt
$ go get github.com/golang-jwt/jwt

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

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

Папки

$ mkdir -p cmd pkg/config/envs pkg/db pkg/models pkg/pb pkg/services pkg/utils

Файлы

$ touch Makefile cmd/main.go pkg/config/envs/dev.env pkg/config/config.go
$ touch pkg/pb/auth.proto pkg/db/db.go pkg/models/auth.go pkg/services/auth.go pkg/utils/hash.go pkg/utils/jwt.go

Структура проекта выглядит так:

Makefile

Здесь нам нужен Makefile, а также для сокращения наших команд.

Давайте добавим код в Makefile

Прото файл

Нам нужен один и тот же прото-файл на обоих концах, на стороне микросервиса и на стороне шлюза API.

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

Создать файл Protobuf

Нам нужно сгенерировать файл protobuf.

$ make proto

Переменные среды

Переменные, которые нам нужны здесь, это, конечно же, порт нашего сервера gRPC, затем нам нужен URL-адрес базы данных и нам нужен секретный ключ для JWT.

Давайте добавим код в pkg/config/envs/dev.env

Конфигурация

Теперь нам нужно создать файл config.go для этого микросервиса.

Давайте добавим код в pkg/config/config.go

Модель базы данных

В этой модели мы создаем таблицу в нашей базе данных auth_svc. Помните, мы создали базу данных в PostgreSQL под названием auth_svc.

Давайте добавим код в pkg/models/auth.go

Подключение к базе данных

Здесь мы подключаемся к этой базе данных.

Функция db.AutoMigrate автоматически создаст для нас таблицу, как только мы запустим это приложение.

Давайте добавим код в pkg/db/db.go

Хэш-помощник

В этом файле у нас есть две функции для кодирования пароля с помощью bcrypt, а также функция проверки.

Давайте добавим код в pkg/utils/hash.go

Помощник JWT

В этом помощнике мы создаем и проверяем веб-токены JSON на основе секретного ключа, который мы определили ранее в файле dev.env.

Давайте добавим код в pkg/utils/jwt.go

Служба аутентификации

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

Давайте добавим код в pkg/services/auth.go

Основной файл

И последнее, но не менее важное: нам нужно загрузить этот микросервис.

Давайте добавим код в cmd/main.go

Вот и все, мы наконец закончили с частью 1, которая включает шлюз API и первый микросервис для аутентификации.

Теперь мы можем сгенерировать файл protobuf и запустить сервер.

$ make server

Вывод в консоли будет таким:

Тестирование микросервиса аутентификации и шлюза API

Теперь мы можем отправить два HTTP-запроса на наш шлюз API. Убедитесь, что оба приложения запущены и работают. Шлюз API на порту 3000 и микрослужба аутентификации на порту 52001.

Зарегистрируйте нового пользователя

curl --request POST \
  --url http://localhost:3000/auth/register \
  --header 'Content-Type: application/json' \
  --data '{
 "email": "[email protected]",
 "password": "1234567"
}'

Войти пользователем

curl --request POST \
  --url http://localhost:3000/auth/login \
  --header 'Content-Type: application/json' \
  --data '{
 "email": "[email protected]",
 "password": "1234567"
}'

Ответ на этот запрос важен, потому что этот запрос вернет нужный нам веб-токен JSON, как только мы закончим другой микросервис в части 2 этой серии статей.

Ответ будет выглядеть следующим образом:

{
 "status": 200,
 "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2ODAxMTk5NzAsImlzcyI6ImdvLWdycGMtYXV0aC1zdmMiLCJJZCI6MiwiRW1haWwiOiJlbG9uQG11c2suY29tIn0.oDirdoryUDBaOtbAUzVgtwTeakNi9SptPyW7ftobdrI"
}

Часть 2:



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

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

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

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

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