.. | ||
images | ||
message-service | ||
nginx-conf | ||
user-service | ||
docker-compose.yml | ||
README.md |
Лабораторная работа 3. REST API, Gateway и синхронный обмен между микросервисами
Задание на лабораторную работу
- Создать 2 микросервиса, реализующих CRUD на связанных сущностях.
- Реализовать механизм синхронного обмена сообщениями между микросервисами.
- Реализовать шлюз на основе прозрачного прокси-сервера 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
Скриншоты
Результаты сборки и запуска программ в консоли
Ссылка на видео:
https://drive.google.com/file/d/19pw4LWiuzK2tDHlSSbKbxNWPsvbUzWwd/view?usp=sharing