161 lines
7.6 KiB
Markdown
161 lines
7.6 KiB
Markdown
|
# Лабораторная работа 3. REST API, Gateway и синхронный обмен между микросервисами
|
|||
|
### Задание на лабораторную работу
|
|||
|
1. Создать 2 микросервиса, реализующих CRUD на связанных сущностях.
|
|||
|
2. Реализовать механизм синхронного обмена сообщениями между микросервисами.
|
|||
|
3. Реализовать шлюз на основе прозрачного прокси-сервера nginx.
|
|||
|
|
|||
|
***
|
|||
|
### Как запустить лабораторную работу
|
|||
|
Для сборки и запуска программ необходимо перейти в директорию с файлом `docker-compose.yaml` и выполнить команду:
|
|||
|
```
|
|||
|
docker-compose up -d
|
|||
|
```
|
|||
|
***
|
|||
|
### Описание работы
|
|||
|
Были созданы два микросервиса на *java*, каждый реализует CRUD-операции: список записей, подробности конкретной записи, создание, удаление и изменение записи.
|
|||
|
Микросервисы реализованы при помощи фреймворка *spring*.
|
|||
|
|
|||
|
**Описание сущностей:**
|
|||
|
- *user* - пользователь. Поля: *id* (уникальный идентификатор пользователя), *fullName* (ФИО), *phoneNumber* (номер телефона), *role* (роль - ученик/репетитор).
|
|||
|
- *message* - сообщение. Поля: *id* (уникальный идентификатор сообщения), *text* (текст), *status* (статус - отправлено/получено/прочитано), *date* (дата отправки), *userId* (id пользователя).
|
|||
|
|
|||
|
Сущности связаны отношением один-ко-многим (пользователь-сообщения).
|
|||
|
|
|||
|
**Реализация синхронного обмена:**
|
|||
|
|
|||
|
Синхронный обмен между сообщениями реализуется при помощи RestTemplate.
|
|||
|
При получении информации о сообщении через GET запрос к user-service получаются данные о пользователе-отправителе сообщения.
|
|||
|
|
|||
|
Пример реализации при получении записи о сообщении в `MessageService`:
|
|||
|
```
|
|||
|
private final MessageRepository messageRepository;
|
|||
|
private final RestTemplate restTemplate;
|
|||
|
private final String URL = "http://user-service:8085/user/";
|
|||
|
|
|||
|
@Autowired
|
|||
|
public MessageService(MessageRepository messageRepository, RestTemplate restTemplate) {
|
|||
|
this.messageRepository = messageRepository;
|
|||
|
this.restTemplate = restTemplate;
|
|||
|
}
|
|||
|
|
|||
|
@Transactional(readOnly = true)
|
|||
|
public MessageWithUserInfoDto findMessage(Long id) {
|
|||
|
final Message message = messageRepository.findById(id).orElse(null);
|
|||
|
if (message == null) {
|
|||
|
throw new MessageNotFoundException(id);
|
|||
|
}
|
|||
|
UserInfoDto userInfo = restTemplate.getForObject(URL + message.getUserId(), UserInfoDto.class);
|
|||
|
return new MessageWithUserInfoDto(message, userInfo);
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
**Dockerfile**
|
|||
|
|
|||
|
Используется базовый образ *openjdk:17-jdk*, на основе которого будет создан контейнер.
|
|||
|
Внутри контейнера создается директория `/usr/src/app/`, после устанавливается рабочая директория и файлы из каталога, где находится Dockerfile, копируются внутрь контейнера в директорию `/usr/src/app/`.
|
|||
|
Выполняется сборка проекта с помощью инструмента gradlew. Задается порт и указывается точка входа для контейнера. Запуск java-приложения осуществляется посредством запуска jar-файла.
|
|||
|
|
|||
|
Содержимое `Dockerfile` для сервиса `user-service`:
|
|||
|
```
|
|||
|
FROM openjdk:17
|
|||
|
RUN mkdir -p /usr/src/app/
|
|||
|
WORKDIR /usr/src/app/
|
|||
|
COPY . /usr/src/app/
|
|||
|
RUN ./gradlew clean build
|
|||
|
EXPOSE 8085
|
|||
|
ENTRYPOINT ["java","-jar","build/libs/user-service-1.0-SNAPSHOT.jar"]
|
|||
|
```
|
|||
|
Аналогично был составлен `Dockerfile` для сервиса `message-service`.
|
|||
|
|
|||
|
**Файл конфигурации nginx.conf**
|
|||
|
|
|||
|
Файл `nginx.conf` содержит конфигурацию для сервера *nginx*.
|
|||
|
Конфигурация позволяет перенаправлять запросы, начинающиеся с /user-service/ на сервер user-service на порту 8085, а запросы, начинающиеся с /message-service/, на сервер message-service на порту 8086.
|
|||
|
```
|
|||
|
server {
|
|||
|
listen 80;
|
|||
|
listen [::]:80;
|
|||
|
server_name localhost;
|
|||
|
|
|||
|
location /user-service/ {
|
|||
|
proxy_pass http://user-service:8085/;
|
|||
|
proxy_set_header Host $host;
|
|||
|
proxy_set_header X-Real-IP $remote_addr;
|
|||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|||
|
proxy_set_header X-Forwarded-Prefix /user-service;
|
|||
|
}
|
|||
|
|
|||
|
location /message-service/ {
|
|||
|
proxy_pass http://message-service:8086/;
|
|||
|
proxy_set_header Host $host;
|
|||
|
proxy_set_header X-Real-IP $remote_addr;
|
|||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|||
|
proxy_set_header X-Forwarded-Prefix /message-service;
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
**Файл конфигурации docker-compose.yml**
|
|||
|
|
|||
|
В файле `docker-compose.yml` указана версия синтаксиса *Docker Compose*, определен список сервисов, которые будут развернуты в приложении, и определена сеть с именем "network", которая будет использоваться для связи между контейнерами.
|
|||
|
Файл определяет три сервиса: *user-service*, *message-service* и *nginx*. Для сервисов user-service и message-service используются образы приложений, созданные при помощи Dockerfile.
|
|||
|
Сервис *nginx* использует образ *nginx*.
|
|||
|
Параметр *depends_on* определяет зависимости сервисов (*nginx* зависит от сервисов *user-service* и *message-service* и разворачивается только после их запуска), в *ports* настраивается проброс портов.
|
|||
|
```
|
|||
|
version: '3'
|
|||
|
|
|||
|
services:
|
|||
|
user-service:
|
|||
|
build:
|
|||
|
context: /user-service
|
|||
|
dockerfile: Dockerfile
|
|||
|
ports:
|
|||
|
- 8085:8085
|
|||
|
networks:
|
|||
|
- network
|
|||
|
|
|||
|
message-service:
|
|||
|
build:
|
|||
|
context: /message-service
|
|||
|
dockerfile: Dockerfile
|
|||
|
ports:
|
|||
|
- 8086:8086
|
|||
|
networks:
|
|||
|
- network
|
|||
|
|
|||
|
nginx:
|
|||
|
image: nginx
|
|||
|
ports:
|
|||
|
- 8087:80
|
|||
|
networks:
|
|||
|
- network
|
|||
|
volumes:
|
|||
|
- ./nginx-conf:/etc/nginx/conf.d
|
|||
|
depends_on:
|
|||
|
- user-service
|
|||
|
- message-service
|
|||
|
|
|||
|
networks:
|
|||
|
network:
|
|||
|
driver: bridge
|
|||
|
```
|
|||
|
|
|||
|
***
|
|||
|
### Скриншоты
|
|||
|
***Результаты сборки и запуска программ в консоли***
|
|||
|
![](images/console.jpg)
|
|||
|
|
|||
|
***Образы в Dockerhub***
|
|||
|
![](images/dockerhub1.jpg)
|
|||
|
|
|||
|
***Контейнеры в Dockerhub***
|
|||
|
![](images/dockerhub2.jpg)
|
|||
|
|
|||
|
***Информация по пользователю***
|
|||
|
![](images/user.jpg)
|
|||
|
|
|||
|
***Информация по сообщению***
|
|||
|
![](images/message.jpg)
|
|||
|
|
|||
|
### Ссылка на видео:
|
|||
|
https://drive.google.com/file/d/19pw4LWiuzK2tDHlSSbKbxNWPsvbUzWwd/view?usp=sharing
|