# Лабораторная работа №3 - REST API, Gateway и синхронный обмен между микросервисами

Цель: изучение шаблона проектирования gateway, построения синхронного обмена между микросервисами и архитектурного стиля RESTful API.

Задачи:

1. Создать 2 микросервиса, реализующих CRUD на связанных сущностях.
2. Реализовать механизм синхронного обмена сообщениями между микросервисами.
3. Реализовать шлюз на основе прозрачного прокси-сервера nginx.

## Создание микросервисов

Создать два микросервиса.

Каждый сервис реализует CRUD-операции: список записей, подробности конкретной записи, создание, удаление и изменение записи.

В качестве хранилища данных может выступать оперативная память приложения или база данных.

Сущности необходимо подобрать по следующим критериям:

1. Они должны быть связаны с предполагаемой темой диплома.
2. Они должны быть связаны как `1-ко-многим``.

> Например, одна сущность - книга в библиотеке, вторая - абонемент.
>
> Поля абонемента: УИД (уникальный идентификатор) абонемента, Номер, ФИО читателя, Дата выдачи.
> Поля книги: УИД книги, Автор, Название, Год издания, УИД абонемента, на котором сейчас находится книга.

Общение между сервисами должно происходить при помощи API, реализованного при помощи архитектурного стиля проектирования REST.
То есть необходимо реализовать следующие endpoints:

1. "GET /" - Получение списка записей.
   Должен возвращать массив моделей.
2. "GET /{uuid}" - Получение подробностей записи по УИД (uuid).
   Должен возвращать модель или ошибку 404.
3. "POST /" - Создание новой записи.
   Принимает на вход данные. Должен возвращать модель из п.2.
4. "PUT /{uuid}" - Обновление записи по УИД.
   Принимает на вход новые данные. Должен возвращать модель из п.2 или ошибку 404.
5. "DELETE /{uuid}" - Удаление записи по УИД.
   Возвращает коды 200 при успехе и 404, если запись не найдена.

Пример модели абонемента для списка и подробностей:

```json
{
	"uuid": "8f036445-a5bd-401c-926e-840f9de795cd",
	"number": 135,
	"fullName": "Иванов И.И.",
	"issued": "2023-10-18T05:41:00Z"
}
```

Пример модели абонемента для создания или изменения:

```json
{
	"number": 135,
	"fullName": "Иванов И.И.",
	"issued": "2023-10-18T05:41:00Z"
}
```

> Как видите, нет УИДа, т.к. он присваивается системой, и изменять мы его не можем.

Пример модели книги для списка:

```json
{
	"uuid": "8740d660-b251-4272-8535-be7ec3748d4b",
	"author": "J.K.R.",
	"subject": "HP and PS",
	"year": 1997,
	"subscriptionUuid": "8f036445-a5bd-401c-926e-840f9de795cd"
}
```

Пример модели книги для подробностей:

```json
{
	"uuid": "8740d660-b251-4272-8535-be7ec3748d4b",
	"author": "J.K.R.",
	"subject": "HP and PS",
	"year": 1997,
	"subscriptionUuid": "8f036445-a5bd-401c-926e-840f9de795cd",
	"subscriptionInfo": {
		"number": 135,
		"fullName": "Иванов И.И.",
		"issued": "2023-10-18T05:41:00Z"
	}
}
```

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

Пример модели книги для создания или изменения:

```json
{
	"author": "J.K.R.",
	"subject": "HP and PS",
	"year": 1997,
	"subscriptionUuid": "8f036445-a5bd-401c-926e-840f9de795cd"
}
```

Как понять, куда обращаться микросервису книг для получения данных об абонементах?
Нам здесь поможет docker compose: код в "service" совпадает с хостом, куда следует обращаться.

## Реализация синхронного обмена

Как реализовать непосредственно работу с endpoints?
Например, использовать ASP.NET Core Minimal APIs.
[Небольшой пример, который это показывает](./example_1.cs).

Как вызвать синхронно данные с соседнего микросервиса?
Через HTTP-клиент!
[Небольшой пример, который это показывает](./example_2.cs).

## Реализация gateway при помощи nginx

Один сервер, несколько location, proxy_pass по хосту из docker-compose.yml, открытые порты наружу и... всё.

[Пример файла с настройкой nginx](./example_nginx.conf).

[Ещё один пример связи воркеров и nginx](../../tasks/moiseev-vv/lab_3).