206 lines
8.9 KiB
Markdown
206 lines
8.9 KiB
Markdown
# Лабораторная работа №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 |