Распределённая система на Kotlin для подбора MD5‑хэшей методом перебора.
Основана на микросервисной архитектуре с брокером сообщений RabbitMQ и
документоориентированным хранилищем MongoDB.
Все компоненты автоматически восстанавливаются после сбоев и могут быть
развёрнуты в Docker Swarm на одном или нескольких хостах.
Система состоит из трёх логических сервисов, запускаемых в Docker-контейнерах:
- Принимает от клиентов GraphQL-запросы (мутации
crackHashи запросыhashStatus). - Делит общую задачу перебора на независимые части.
- Сохраняет состояние каждой задачи в отказоустойчивой MongoDB (Replica Set).
- Публикует части задач в очередь RabbitMQ (JSON-сообщения).
- Подписывается на очередь ответов и сохраняет найденные слова в MongoDB.
- При старте восстанавливает задачи, которые были в работе до падения менеджера.
- Подписывается на очередь задач RabbitMQ.
- Выполняет перебор MD5 в заданном диапазоне (генерирует слова, вычисляет хэш).
- При нахождении совпадения немедленно публикует результат в очередь ответов.
- В случае сбоя воркера RabbitMQ автоматически переотправляет задачу другому экземпляру.
- MongoDB Replica Set (3 узла) — персистентное хранение всех задач и результатов.
- RabbitMQ — брокер сообщений с персистентными очередями и ручным подтверждением (manual ack).
- Docker Swarm — оркестрация контейнеров на кластере из 5 узлов (1 менеджер + 4 воркера).
Это нужно, чтобы gateway держался отдельно, чтобы его перезапуск не влиял на базу или worker.
RabbitMQ лучше тоже держать отдельно, чтобы брокер не конкурировал с БД.
| Вид сбоя | Поведение системы |
|---|---|
| Остановка менеджера | Состояние задач сохранено в MongoDB. При перезапуске менеджер заново отправляет в очередь задачи со статусом PENDING_WORKER и получает накопившиеся ответы. |
| Остановка primary‑узла MongoDB | Replica Set автоматически выбирает нового лидера. Система продолжает работу без потери данных. |
| Остановка RabbitMQ | Gateway сохраняет задачи в БД со статусом PENDING_QUEUE и повторяет отправку после восстановления брокера. Сообщения в очередях персистентны и не теряются при рестарте RabbitMQ. |
| Падение воркера во время обработки | Сообщение остаётся неподтверждённым (unacked). RabbitMQ возвращает его в очередь и передаёт другому воркеру. |
| Отсутствие доступных воркеров в момент создания задачи | Сообщения накапливаются в очереди и будут обработаны сразу после появления воркеров. |
- Язык: Kotlin
- Фреймворк: Ktor (Gateway)
- API: GraphQL (
graphql-kotlin) - Брокер сообщений: RabbitMQ (AMQP 0-9-1)
- Хранилище: MongoDB 7.0 (Replica Set, Write Concern
majority) - Сериализация: JSON (
kotlinx.serialization) - Оркестрация: Docker, Docker Swarm
- Эмуляция кластера: Docker-in-Docker (dind)
- Нагрузочное тестирование: k6
CrackHash/
├── common/ # общие классы (модели сообщений, сервис RabbitMQ)
├── gateway/ # Ktor-приложение с GraphQL API и логикой менеджера
├── worker/ # вычислительный сервис – перебор MD5
├── docker-compose.yml # описание стека (для Docker Swarm)
├── docker-compose.local.yml # описание для локального запуска
├── mongo-init.js # скрипт инициализации репликасета MongoDB
├── index.html # простой веб-клиент
├── gateway/src/test/test.ps1 # скрипт для запуска задачи
├── gateway/src/test/check_status.ps1 # скрипт проверки статуса
└── README.md
Используется для разработки и отладки. Все сервисы запускаются на одном хосте в bridge-сети.
-
Убедитесь, что Docker Desktop запущен и переключён на Linux‑контейнеры.
-
Создайте
docker-compose.local.ymlна основе основного файла, заменив драйвер сети наbridge(или просто используйте готовый файл, где уже стоитdriver: bridge).
В текущемdocker-compose.ymlуже указанdriver: bridge– его можно использовать как есть для локального запуска. -
Соберите и запустите стек:
docker compose -f docker-compose.local.yml up --build
Для масштабирования используйте:
docker compose -f docker-compose.local.yml up --scale worker=3
Первый раз MongoDB скачается с Docker Hub, а Gateway и Worker соберутся из исходников.
-
Дождитесь инициализации репликасета
Сервисmongo-initвыполнит скриптmongo-init.jsи выведетReplica set initiated.
В логах Gateway должно появитьсяResponding at http://0.0.0.0:8080. -
Отправьте тестовую задачу (PowerShell):
.\gateway\src\test\test.ps1
Вы получите
requestId. -
Проверьте статус:
.\gateway\src\test\check_status.ps1 -RequestId "ваш-requestId"
Статус сменится с
IN_PROGRESSнаREADY, когда все части обработаны. -
Графический веб-клиент: откройте
index.htmlв браузере, введите хэш и максимальную длину, нажмите «Взломать». -
Остановка:
docker compose -f docker-compose.local.yml down -v
Для эмуляции кластера из 5 узлов используется Docker-in-Docker (dind).
.\make_images.ps1-
Запустите 5 dind‑контейнеров:
.\create_nodes.ps1
-
Инициализируйте Swarm и получите токены присоединения к кластеру:
docker exec -it node-1 sh -c "docker swarm init" docker exec -it node-1 sh -c "docker swarm join-token manager"
-
Присоедините их к кластеру:
.\attach_nodes_to_cluster.ps1 -WorkerToken <ваш токен воркера> -ManagerToken <ваш токен менеджера>
-
Навесьте метки узлов (для фиксированного размещения сервисов):
.\adding_labels_to_nodes.ps1
-
Перенесите нужные файлы и образы на узлы (на которых они потребуются):
.\load_data_to_nodes.ps1
-
Задеплойте стек:
docker exec -it node-1 sh -c "docker stack deploy -c /docker-compose.yml crackhash"
-
Проверьте состояние:
docker exec -it node-1 sh -c "docker stack services crackhash" docker exec -it node-1 sh -c "docker stack ps crackhash"
-
Инициализация репликасета MongoDB – сервис
mongo-initсделает это автоматически. -
Тестирование – Gateway доступен на порту 8080 любого узла Swarm (mesh‑сеть). Используйте
test.ps1иindex.html.
Подключитесь к контейнеру primary‑узла (обычно mongo1):
# Локальный запуск
docker exec -it crackhash-mongo1-1 mongosh
# В Swarm – узнайте ID контейнера через docker ps и выполните docker execВнутри оболочки:
use crackhash
db.tasks.find().pretty()Для поиска конкретной задачи:
db.tasks.find({ requestId: "идентификатор" }).pretty()gateway/src/test/test.ps1– отправляет GraphQL‑мутацию на взлом.gateway/src/test/result_test.ps1– запрашивает статус поrequestId.
Файл index.html содержит простой веб‑интерфейс:
- Поле для MD5‑хэша и максимальной длины слова.
- Кнопка «Взломать» отправляет мутацию, затем автоматически опрашивает статус.
- Отображает найденные слова.
Для работы требует включённого CORS на Gateway (добавлен плагин ktor-server-cors).
Данная система демонстрирует принципы построения отказоустойчивых распределённых приложений:
- Асинхронная обработка через очереди сообщений.
- Персистентное хранение состояния с автоматическим восстановлением.
- Репликация базы данных для защиты от потери узла.
- Оркестрация контейнеров для автоматического перезапуска и масштабирования.