senkin_alexander_lab_2 is ready
@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="Go" enabled="true" />
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
|
53
senkin_alexander_lab_2/README.md
Normal file
@ -0,0 +1,53 @@
|
||||
# Лабораторная работа №2 - Разработка простейшего распределенного приложения
|
||||
|
||||
Цель: изучение техники создания простого распределенного приложения.
|
||||
|
||||
Задачи:
|
||||
|
||||
- Согласно вышему варианту (выбирайте любой) разработать два приложения такие, что результат первого является исходными данными для второго.
|
||||
- Изучить файлы сборки образов docker и разработать их для созданных приложений.
|
||||
- Собрать файл docker-compose.yml для запуска приложений. Разобраться с монтированием каталогов из хост-системы.
|
||||
- Правильно закоммитить результат без лишних файлов.
|
||||
- Оформить pull request по правилам и отправить его на проверку.
|
||||
|
||||
# Разработка двух приложений
|
||||
|
||||
Было решено для первого приложения(worker_1) выбрать 1 вариант - Ищет в каталоге /var/data файл с наибольшим количеством строк и перекладывает его в /var/result/data.txt
|
||||
Для второго приложения(worker_2) выбрать 0 вариант - сохраняет произзведение первого и последнего числа из файла /var/result/data.txt в /var/result/result.txt
|
||||
|
||||
Разработка ведется на языке Go
|
||||
|
||||
![img.png](img.png)
|
||||
|
||||
# Запуск
|
||||
|
||||
Запуск контейнеров производится командой "docker-compose up -d"
|
||||
|
||||
# Работа программы
|
||||
|
||||
- Создание двух деррикторий: worker_1 и worker_2 для реализаций двух программ.
|
||||
- Создание go.mod для обоих программ и реализация этих программ.
|
||||
- Описание Dockerfile для создания образов для обоих программ.
|
||||
- ![img_2.png](img_2.png) ![img_3.png](img_3.png)
|
||||
- Создание двух репозиториев: data, result, для монтирования их в контейнеры, а также заполнение папки data тремя файлами.
|
||||
- ![img_4.png](img_4.png)
|
||||
- Описание docker-compose для запуска контейнеров, реализуется build для создания образов на основе dockerfile и у второго контейнера описавыется зависимость depends_on от первого контейнера, чтобы сначала успевал запуститься первый контейнер, а за ним запускался второй. Также описываются volumes, для монтирование папок data и result в контейнеры.
|
||||
- ![img_5.png](img_5.png)
|
||||
- Сборка и запуска контейнеров.
|
||||
- ![img_6.png](img_6.png)
|
||||
- Проверка в Docker Desktop контейнеров и образов.
|
||||
- ![img_7.png](img_7.png)
|
||||
- ![img_8.png](img_8.png)
|
||||
- Смотрим, что выдает нам первый воркер в консоль. Он говорит, что первый файл с названием file1.txt имеет 4 строки, и это больше, чем в других файлах. Также текст этого файла был скопирован в файл data.txt
|
||||
- ![img_9.png](img_9.png)
|
||||
- Смотрим, что выдает нам второй воркер в консоль. Он говорит, что результат умножения сохранен в файл result.txt, а также выдает нам число, лежащее в этом файле.
|
||||
- ![img_10.png](img_10.png)
|
||||
- Смотрим, что при запуске контейнеров действительно в папке result создалось два файла data.txt и result.txt
|
||||
- ![img_11.png](img_11.png)
|
||||
- Смотрим, что лежит в эти файлах. В файле data.txt действительно лежат числа из file1.txt, а в файле result.txt лежит результат умножения первого на последнее число.
|
||||
- ![img_12.png](img_12.png)
|
||||
- ![img_13.png](img_13.png)
|
||||
|
||||
# Видео
|
||||
|
||||
Видео с разбором лабораторной работы - https://youtu.be/JHDQOQBBPUs
|
4
senkin_alexander_lab_2/data/file1.txt
Normal file
@ -0,0 +1,4 @@
|
||||
525 785 99856
|
||||
1000 7984 545102
|
||||
513 84651321 564
|
||||
654 6548 321315
|
2
senkin_alexander_lab_2/data/file2.txt
Normal file
@ -0,0 +1,2 @@
|
||||
42432 54654 5212
|
||||
1524 458 3526
|
3
senkin_alexander_lab_2/data/file3.txt
Normal file
@ -0,0 +1,3 @@
|
||||
546 546542 21354
|
||||
2548 545 4645
|
||||
546 5473 5464
|
18
senkin_alexander_lab_2/docker-compose.yml
Normal file
@ -0,0 +1,18 @@
|
||||
services:
|
||||
worker1:
|
||||
build:
|
||||
context: /worker_1
|
||||
dockerfile: Dockerfile
|
||||
volumes:
|
||||
- C:\Users\Mamoru\GolandProjects\DAS_2023_1\senkin_alexander_lab_2\data:/var/data
|
||||
- C:\Users\Mamoru\GolandProjects\DAS_2023_1\senkin_alexander_lab_2\result:/var/result
|
||||
worker2:
|
||||
build:
|
||||
context: /worker_2
|
||||
dockerfile: Dockerfile
|
||||
volumes:
|
||||
- C:\Users\Mamoru\GolandProjects\DAS_2023_1\senkin_alexander_lab_2\data:/var/data
|
||||
- C:\Users\Mamoru\GolandProjects\DAS_2023_1\senkin_alexander_lab_2\result:/var/result
|
||||
depends_on:
|
||||
- worker1
|
||||
|
BIN
senkin_alexander_lab_2/img.png
Normal file
After Width: | Height: | Size: 3.5 KiB |
BIN
senkin_alexander_lab_2/img_1.png
Normal file
After Width: | Height: | Size: 9.9 KiB |
BIN
senkin_alexander_lab_2/img_10.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
senkin_alexander_lab_2/img_11.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
senkin_alexander_lab_2/img_12.png
Normal file
After Width: | Height: | Size: 2.7 KiB |
BIN
senkin_alexander_lab_2/img_13.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
senkin_alexander_lab_2/img_2.png
Normal file
After Width: | Height: | Size: 9.9 KiB |
BIN
senkin_alexander_lab_2/img_3.png
Normal file
After Width: | Height: | Size: 9.9 KiB |
BIN
senkin_alexander_lab_2/img_4.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
senkin_alexander_lab_2/img_5.png
Normal file
After Width: | Height: | Size: 36 KiB |
BIN
senkin_alexander_lab_2/img_6.png
Normal file
After Width: | Height: | Size: 59 KiB |
BIN
senkin_alexander_lab_2/img_7.png
Normal file
After Width: | Height: | Size: 29 KiB |
BIN
senkin_alexander_lab_2/img_8.png
Normal file
After Width: | Height: | Size: 70 KiB |
BIN
senkin_alexander_lab_2/img_9.png
Normal file
After Width: | Height: | Size: 13 KiB |
4
senkin_alexander_lab_2/result/data.txt
Normal file
@ -0,0 +1,4 @@
|
||||
525 785 99856
|
||||
1000 7984 545102
|
||||
513 84651321 564
|
||||
654 6548 321315
|
1
senkin_alexander_lab_2/result/result.txt
Normal file
@ -0,0 +1 @@
|
||||
168690375
|
13
senkin_alexander_lab_2/worker_1/Dockerfile
Normal file
@ -0,0 +1,13 @@
|
||||
FROM golang:latest
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY go.mod .
|
||||
|
||||
RUN go mod download
|
||||
|
||||
COPY worker_1.go .
|
||||
|
||||
RUN go build -o myapp
|
||||
|
||||
CMD ["/app/myapp"]
|
3
senkin_alexander_lab_2/worker_1/go.mod
Normal file
@ -0,0 +1,3 @@
|
||||
module DAS_2023_1/senkin_alexander_lab_2/worker_1
|
||||
|
||||
go 1.20
|
71
senkin_alexander_lab_2/worker_1/worker_1.go
Normal file
@ -0,0 +1,71 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
func main() {
|
||||
sourceDir := "/var/data"
|
||||
destinationFile := "/var/result/data.txt"
|
||||
|
||||
if _, err := os.Stat(destinationFile); os.IsNotExist(err) {
|
||||
file, err := os.Create(destinationFile)
|
||||
if err != nil {
|
||||
log.Println("Ошибка при создании файла:", err)
|
||||
return
|
||||
}
|
||||
file.Close()
|
||||
}
|
||||
|
||||
files, err := ioutil.ReadDir(sourceDir)
|
||||
if err != nil {
|
||||
log.Println("Ошибка при чтении каталога:", err)
|
||||
return
|
||||
}
|
||||
|
||||
var maxLines int
|
||||
var maxLinesFile string
|
||||
|
||||
for _, file := range files {
|
||||
if !file.IsDir() {
|
||||
filePath := filepath.Join(sourceDir, file.Name())
|
||||
lines, err := countLines(filePath)
|
||||
if err != nil {
|
||||
log.Printf("Ошибка при подсчете строк в файле %s: %v\n", filePath, err)
|
||||
continue
|
||||
}
|
||||
if lines > maxLines {
|
||||
maxLines = lines
|
||||
maxLinesFile = filePath
|
||||
}
|
||||
}
|
||||
}
|
||||
if maxLinesFile != "" {
|
||||
data, err := ioutil.ReadFile(maxLinesFile)
|
||||
if err != nil {
|
||||
log.Printf("Ошибка при чтении файла: %v\n", err)
|
||||
return
|
||||
}
|
||||
err = ioutil.WriteFile(destinationFile, data, 0644)
|
||||
if err != nil {
|
||||
log.Printf("Ошибка при записи файла: %v\n", err)
|
||||
return
|
||||
}
|
||||
log.Printf("Файл %s с наибольшим количеством строк (%d) скопирован в %s\n", maxLinesFile, maxLines, destinationFile)
|
||||
} else {
|
||||
log.Println("Не удалось найти файлы в каталоге /var/data.")
|
||||
}
|
||||
}
|
||||
|
||||
func countLines(filePath string) (int, error) {
|
||||
data, err := ioutil.ReadFile(filePath)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
lines := len(bytes.Split(data, []byte("\n"))) - 1
|
||||
return lines, nil
|
||||
}
|
13
senkin_alexander_lab_2/worker_2/Dockerfile
Normal file
@ -0,0 +1,13 @@
|
||||
FROM golang:latest
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY go.mod .
|
||||
|
||||
RUN go mod download
|
||||
|
||||
COPY worker_2.go .
|
||||
|
||||
RUN go build -o myapp
|
||||
|
||||
CMD ["/app/myapp"]
|
3
senkin_alexander_lab_2/worker_2/go.mod
Normal file
@ -0,0 +1,3 @@
|
||||
module DAS_2023_1/senkin_alexander_lab_2/worker_2
|
||||
|
||||
go 1.20
|
89
senkin_alexander_lab_2/worker_2/worker_2.go
Normal file
@ -0,0 +1,89 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func main() {
|
||||
dataFilePath := "/var/result/data.txt"
|
||||
resultFilePath := "/var/result/result.txt"
|
||||
|
||||
if _, err := os.Stat(resultFilePath); os.IsNotExist(err) {
|
||||
file, err := os.Create(resultFilePath)
|
||||
if err != nil {
|
||||
log.Println("Ошибка при создании файла:", err)
|
||||
return
|
||||
}
|
||||
file.Close()
|
||||
}
|
||||
|
||||
_, err := os.Stat(dataFilePath)
|
||||
if err != nil {
|
||||
log.Fatal("Файл data.txt не сущесвует, выполните первую программу перед запуском второй")
|
||||
}
|
||||
|
||||
data, err := ioutil.ReadFile(dataFilePath)
|
||||
if err != nil {
|
||||
fmt.Printf("Ошибка при чтении файла %s: %v\n", dataFilePath, err)
|
||||
return
|
||||
}
|
||||
|
||||
content := string(data)
|
||||
|
||||
lines := bufio.NewScanner(strings.NewReader(content))
|
||||
|
||||
first := 0
|
||||
last := 0
|
||||
firstFound := false
|
||||
var numbersFound bool
|
||||
|
||||
for lines.Scan() {
|
||||
line := lines.Text()
|
||||
numbers := strings.Fields(line)
|
||||
if len(numbers) > 0 {
|
||||
// Преобразуем первое и последнее число в числа с плавающей точкой
|
||||
if !firstFound {
|
||||
first, err = strconv.Atoi(numbers[0])
|
||||
if err != nil {
|
||||
log.Fatalf("Ошибка при преобразовании первого числа: %v", err)
|
||||
}
|
||||
firstFound = true
|
||||
}
|
||||
last, err = strconv.Atoi(numbers[len(numbers)-1])
|
||||
if err != nil {
|
||||
log.Fatalf("Ошибка при преобразовании последнего числа: %v", err)
|
||||
}
|
||||
numbersFound = true
|
||||
}
|
||||
}
|
||||
if err := lines.Err(); err != nil {
|
||||
log.Printf("Ошибка при чтении файла: %v\n", err)
|
||||
return
|
||||
}
|
||||
if !numbersFound {
|
||||
log.Fatalf("Не найдены числа в файле %s", dataFilePath)
|
||||
}
|
||||
|
||||
result := first * last
|
||||
outputContent := fmt.Sprintf("%d", result)
|
||||
if err := ioutil.WriteFile(resultFilePath, []byte(outputContent), 0644); err != nil {
|
||||
log.Printf("Ошибка при записи результата в файл: %v\n", err)
|
||||
return
|
||||
}
|
||||
log.Printf("Результат (%d) сохранен в файл %s\n", result, resultFilePath)
|
||||
|
||||
dataResult, err := ioutil.ReadFile(resultFilePath)
|
||||
if err != nil {
|
||||
fmt.Printf("Ошибка при чтении файла %s: %v\n", resultFilePath, err)
|
||||
return
|
||||
}
|
||||
|
||||
contentResult := string(dataResult)
|
||||
log.Println("Результат, лежащий в файле result - ", contentResult)
|
||||
}
|
18
tasks/senkin-ae/lab_2/docker-compose.yml
Normal file
@ -0,0 +1,18 @@
|
||||
services:
|
||||
worker1:
|
||||
build:
|
||||
context: C:\Users\Mamoru\GolandProjects\DAS_2023_1\senkin_alexander_lab_2\worker_1
|
||||
dockerfile: Dockerfile
|
||||
volumes:
|
||||
- C:\Users\Mamoru\GolandProjects\DAS_2023_1\senkin_alexander_lab_2\data:/var/data
|
||||
- C:\Users\Mamoru\GolandProjects\DAS_2023_1\senkin_alexander_lab_2\result:/var/result
|
||||
worker2:
|
||||
build:
|
||||
context: C:\Users\Mamoru\GolandProjects\DAS_2023_1\senkin_alexander_lab_2\worker_2
|
||||
dockerfile: Dockerfile
|
||||
volumes:
|
||||
- C:\Users\Mamoru\GolandProjects\DAS_2023_1\senkin_alexander_lab_2\data:/var/data
|
||||
- C:\Users\Mamoru\GolandProjects\DAS_2023_1\senkin_alexander_lab_2\result:/var/result
|
||||
depends_on:
|
||||
- worker1
|
||||
|