DAS_2023_1/mashkova_margarita_lab_3/README.md

206 lines
8.9 KiB
Markdown
Raw Permalink Normal View History

2023-12-14 09:39:03 +04:00
# Лабораторная работа №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