DAS_2023_1/mashkova_margarita_lab_3/README.md

206 lines
8.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Лабораторная работа №3
## ПИбд-42 Машкова Маргарита
## Задание
1. Создать 2 микросервиса, реализующих CRUD на связанных сущностях.
2. Реализовать механизм синхронного обмена сообщениями между микросервисами.
3. Реализовать шлюз на основе прозрачного прокси-сервера nginx.
## Запуск программы
В директории с файлом `docker-compose.yml` выполнить команду:
```
docker-compose up -d
```
## Описание работы программы
### 2 микросервиса, реализующих CRUD на связанных сущностях:
#### Описание сущностей:
- `Groupe` - группа в университете, содержит 2 атрибута: id и name.
P.S. Слово `group` специально написано неправильно, т.к. такое слово зарезервиравано в СУБД :)
- `Student` - студент, сущность содержит 4 атрибута: id, name, surname, groupeId.
Соответственно сущности связаны один (группа) - ко многим (студенты).
Данные микросервисы, выполняющие CRUD операции над сущностями, реализованы при помощи фреймворка `spring`.
### Реализация механизма синхронного обмена сообщениями между микросервисами:
Реализуется при помощи `RestTemplate`. При получении информации о студенте или о всех студентах отправляется GET запрос
к сервису `groupe-service`, чтобы получить информацию о группе, в которой учится студент.
```
private final RestTemplate restTemplate = new RestTemplate();
private final String URL = "http://groupe-service:8080/groupe/";
public StudentInfoDto findStudentInfo(Integer id){
Student student = studentRepository.findById(id)
.orElseThrow(() -> new RuntimeException(String.format("Student with id %s was not found", id)));
GroupeInfoDto group = restTemplate.getForObject(URL + student.getGroupeId(), GroupeInfoDto.class);
StudentInfoDto studentInfoDto = new StudentInfoDto();
studentInfoDto.setId(id);
studentInfoDto.setName(student.getName());
studentInfoDto.setSurname(student.getSurname());
studentInfoDto.setGroupeInfoDto(group);
return studentInfoDto;
}
```
### Файл конфигурации `docker-compose.yml`:
Для обеспечения работы прокси-сервера nginx в качестве шлюза, необходимо чтобы все управляемые им сервисы находились
в одной сети типа "мост":
```
networks:
my-network:
driver: bridge
```
#### Настройка сервисов:
Для сервиса БД `db-university` используется образ postgres. Также указывается порт взаимодействия,
переменные окружения - логин, пароль для учетной записи в postgres и имя БД. Сервис добавлятся в созданную сеть.
Опция `restart: always` означает, что docker-compose перезапустит контейнер, если тот вдруг остановится.
```
db-university:
image: postgres:latest
container_name: db-university
ports:
- 5432:5432
environment:
POSTGRES_PASSWORD: admin
POSTGRES_USER: admin
POSTGRES_DB: university
restart: always
networks:
- my-network
```
Для сервисов `groupe-service` и `student-service` используются образы приложений, созданные при помощи Dockerfile.
Также указывается порт взаимодействия, зависимость от сервиса БД (контейнер микросервиса запускается только
после запуска контейнера БД).
Сервис добавлятся в созданную сеть.
Опция `restart: always` означает, что docker-compose перезапустит контейнер, если тот вдруг остановится.
```
groupe-service:
build:
context: .
dockerfile: ./groupe-service/Dockerfile
container_name: groupe-service
ports:
- 8080:8080
restart: always
depends_on:
- db-university
networks:
- my-network
student-service:
build:
context: .
dockerfile: ./student-service/Dockerfile
container_name: student-service
ports:
- 8081:8081
restart: always
depends_on:
- db-university
networks:
- my-network
```
### Dockerfile сервиса `groupe-service`:
Используется базовый образ openjdk:17-jdk. Задается рабочая директория /app. В нее копируется jar файл приложения.
Указывается порт, на котором работает приложение. Запуск программы осуществляется посредством запуска jar файла.
```
FROM openjdk:17-jdk
WORKDIR /app
COPY ./groupe-service/build/libs/groupe-service-1.0-SNAPSHOT.jar /app/groupe-service-1.0-SNAPSHOT.jar
EXPOSE 8080
CMD ["java", "-jar", "groupe-service-1.0-SNAPSHOT.jar"]
```
### Dockerfile сервиса `student-service`:
Структура аналогична Dockerfile сервиса `groupe-service`.
```
FROM openjdk:17-jdk
WORKDIR /app
COPY ./student-service/build/libs/student-service-1.0-SNAPSHOT.jar /app/student-service-1.0-SNAPSHOT.jar
EXPOSE 8081
CMD ["java", "-jar", "student-service-1.0-SNAPSHOT.jar"]
```
### Реализация шлюза на основе прозрачного прокси-сервера nginx:
Для сервиса `nginx` используется образ nginx, указывается порт взаимодействия.
`volumes` указывает, что при запуске контейнера, локальный файл конфигураций nginx.conf следует поместить вместо
стандартного файла конфигураций nginx, а `depends_on` указывает, что данный прокси-сервер зависит от обоих сервисов
и разворачивается только после их запуска.
```
nginx:
image: nginx
container_name: nginx
ports:
- "80:80"
networks:
- my-network
volumes:
- ./nginx-conf:/etc/nginx/conf.d
depends_on:
- groupe-service
- student-service
```
### Файл конфигурации `nginx.conf`:
Данная конфигурация позволяет перенаправлять запросы, начинающиеся с `/groupe-service/` на сервер
groupe-service на порту 8080, а запросы, начинающиеся с `/student-service/`, на сервер student-service на порту 8081.
Заголовки запроса также передаются и устанавливаются соответствующие значения для Host и X-Forwarded-Prefix.
Заголовок Host будет установлен в значение $host, заголовок X-Forwarded-Prefix - в значение `/student-service` или
`/groupe-service`.
```
server {
listen 80;
location /groupe-service/ {
proxy_pass_request_headers on;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Prefix '/groupe-service';
proxy_pass http://groupe-service:8080/;
}
location /student-service/ {
proxy_pass_request_headers on;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Prefix '/student-service';
proxy_pass http://student-service:8081/;
}
}
```
## Запуск сервисов
### Результат выполнения команды `docker-compose up -d`:
![Вывод в консоли](build_images.png)
### Созданные образы:
![Созданные образы](images.png)
### Созданные контейнеры:
![Созданные контейнеры](containers.png)
### Результаты синхронного обмена сообщениями между микросервисами:
При получения списка студентов, сервис `student-service` обращается к сервису `groupe-service`,
чтобы отобразить данные группы.
![results](results.png)
Ссылка на видео:
https://youtu.be/BCF0Lxc6veo