АРХИТЕКТУРА ВЕБ-СЕРВИСА ВИРТУАЛЬНОЙ ЛАБОРАТОРИИ ДЛЯ ЭМУЛЯЦИИ АЛГОРИТМОВ ПЛАНИРОВАНИЯ РЕАЛЬНОГО ВРЕМЕНИ

АРХИТЕКТУРА ВЕБ-СЕРВИСА ВИРТУАЛЬНОЙ ЛАБОРАТОРИИ ДЛЯ ЭМУЛЯЦИИ АЛГОРИТМОВ ПЛАНИРОВАНИЯ РЕАЛЬНОГО ВРЕМЕНИ

Авторы публикации

Рубрика

Информационные технологии

Просмотры

3

Журнал

Журнал «Научный лидер» выпуск # 26 (279), Июнь ‘26

Поделиться

В статье описана архитектура веб-сервиса виртуальной лаборатории, предназначенной для запуска и сравнения алгоритмов планирования реального времени. Рассмотрены компоненты серверной части, организация очереди долгих операций, хранение результатов в реляционной базе данных и размещение HTML-отчётов в S3-совместимом объектном хранилище. Отдельное внимание уделено безопасному запуску пользовательского C/C++ кода с предварительной проверкой исходника, компиляцией во временном каталоге и выполнением в ограниченной среде.

Введение

Веб-лаборатория для изучения алгоритмов планирования должна решать две разные задачи. С одной стороны, она должна быть удобной для студента: достаточно открыть страницу, выбрать нагрузку, отправить код и получить отчёт. С другой стороны, серверная часть должна безопасно обрабатывать пользовательские программы, потому что C/C++ код потенциально может содержать ошибки, бесконечные циклы и вызовы, не относящиеся к учебному планировщику.

Обычный синхронный веб-запрос плохо подходит для такого сценария. Компиляция и симуляция могут занимать заметное время, а сравнение нескольких алгоритмов фактически запускает несколько прогонов подряд. Поэтому архитектура должна отделять приём запроса от выполнения долгой операции, сохранять состояние задачи и позволять пользователю позже получить результат.

В разработанной лаборатории эта задача решается за счёт серверной архитектуры с очередью заданий, воркерами, реляционным хранилищем статусов и объектным хранилищем готовых HTML-отчётов. Отдельный слой отвечает за компиляцию и ограниченный запуск пользовательского бинарника.

Общая структура веб-сервиса

Серверная часть реализована как веб-приложение на Kotlin с использованием Ktor. Компонент маршрутизации принимает HTML-страницы и REST-запросы, проверяет параметры и передаёт данные в сервисы задач. В системе предусмотрены два основных сценария: одиночная симуляция и сравнение нескольких алгоритмов на одной нагрузке.

Для хранения состояния используется PostgreSQL. В базе фиксируются параметры запуска, фаза выполнения, диагностические сообщения, JSON-метрики и ключ объекта отчёта. Готовые HTML-отчёты сохраняются не как большие строки в таблице, а как объекты в MinIO. Такой подход разделяет структурированные данные и готовые документы отчёта.

Архитектура построена модульно: пользователь взаимодействует с HTTP-интерфейсом, сервисы задач создают записи в очереди, воркеры забирают задания, CompilerService выполняет сборку и запуск эмулятора, ReportStorage сохраняет результат в объектном хранилище. Благодаря этому отдельные части системы можно развивать независимо друг от друга, а как вариант дополнить новыми модулями саму архитектуру модулями проверки кода или его предобработки.

Таблица 1.

Основные компоненты веб-сервиса виртуальной лаборатории

Компонент

Назначение

Результат работы

Routing

Приём HTML-страниц и REST-запросов, проверка входных параметров.

Создание задач и выдача статуса пользователю.

SimulationJobService

Обработка одиночных симуляций, запуск воркеров.

Переход задачи между состояниями очереди.

ComparisonJobService

Запуск нескольких алгоритмов на одной нагрузке.

Сравнительный отчёт и набор метрик.

CompilerService

Компиляция пользовательского кода и запуск эмулятора.

JSON-метрики либо диагностическая ошибка.

ReportStorage

Сохранение и чтение HTML-отчётов через S3-совместимый API.

Ключ отчёта, доступный из базы данных.

Очередь долгих операций

Для выполнения компиляции и симуляции используется очередь долгих операций. HTTP-запрос не ждёт завершения эксперимента: сервис создаёт запись в базе данных со статусом QUEUED и возвращает пользователю идентификатор задачи. Далее пользователь или интерфейс периодически запрашивает статус.

Воркеры работают независимо от HTTP-запроса. Каждый воркер атомарно забирает свободную задачу из PostgreSQL с помощью конструкции FOR UPDATE SKIP LOCKED. Этот механизм позволяет нескольким воркерам параллельно искать задания, не обрабатывая одну и ту же запись дважды. Если строка уже заблокирована другим воркером, она пропускается, а обработчик берёт следующую доступную задачу [4].

Жизненный цикл задачи включает состояния QUEUED, RUNNING, SUCCESS, COMPILE_ERROR и RUN_ERROR. Такое разделение полезно для пользователя и преподавателя: можно понять, находится ли задача в очереди, выполняется ли она, успешно ли завершилась или остановилась из-за ошибки компиляции либо запуска.

Таблица 2.

Состояния задания в очереди

Состояние

Смысл

Когда возникает

QUEUED

Задание создано и ожидает обработки.

После успешного принятия HTTP-запроса.

RUNNING

Задание забрано воркером.

После атомарного выбора строки из очереди.

SUCCESS

Симуляция завершилась успешно.

После получения JSON-метрик и сохранения отчёта.

COMPILE_ERROR

Ошибка проверки, компиляции или линковки.

При некорректном исходном коде или ошибке сборки.

RUN_ERROR

Ошибка выполнения бинарника или разбора результата.

При тайм-ауте, ненулевом коде возврата или некорректном JSON.

Конвейер компиляции и запуска пользовательского кода

Пользовательская реализация алгоритма передаётся как C или C++ файл, содержащий функцию выбора задачи. Перед компиляцией выполняется предварительная проверка SourceSafetyGuard. Этот компонент не является полноценным формальным статическим анализатором, но он отбрасывает заведомо опасные конструкции: запрещённые include, попытки работы с файлами, сетью и процессами, а также inline assembly.

После предварительной проверки создаётся временный каталог. В него помещается пользовательский файл, объектный файл ядра симулятора и будущий исполняемый файл. Ядро rtos_sim.c и пользовательский файл компилируются отдельно, затем линкуются в единый бинарник. Для C используется стандарт C11, для C++ — C++17. Если компилятор возвращает ошибку или превышает тайм-аут, пользователь получает диагностическое сообщение.

Дополнительная проверка выполняется после компиляции пользовательского объектного файла. Сервис анализирует неопределённые внешние символы через nm и отклоняет объект, если он пытается ссылаться на запрещённые функции вроде system, socket, fork или fopen. Это дополняет текстовую проверку и снижает риск обхода через макросы или косвенные конструкции.

Таблица 3.

Уровни ограничения пользовательского кода

Уровень

Что проверяет или ограничивает

Назначение

SourceSafetyGuard

Размер файла, разрешённые include, запрещённые вызовы, inline assembly.

Раннее отклонение явно опасного исходника.

Проверка объектного файла

Неопределённые внешние символы после компиляции.

Поиск скрытых обращений к запрещённым функциям.

SafeProcess

Тайм-ауты, ограничение stdout/stderr, очищенное окружение процесса.

Контроль внешних процессов компиляции и запуска.

sandbox-runner

chroot, отдельный пользователь, seccomp, no_new_privs, rlimits.

Ограничение уже скомпилированного бинарника.

Безопасное исполнение и хранение отчётов

Сам пользовательский бинарник не выполняется внутри процесса веб-сервера. Он запускается как отдельный процесс через sandbox-runner. Runner создаёт ограниченную среду выполнения: переводит процесс в минимальный корень файловой системы, сбрасывает права до отдельного пользователя, включает no_new_privs, задаёт ограничения процессорного времени, памяти, числа процессов, размера файлов и открытых дескрипторов.

Такой механизм не следует описывать как абсолютную промышленную изоляцию произвольного вредоносного кода. Однако для учебной лаборатории многоуровневая защита существенно снижает риск по сравнению с прямым запуском пользовательского кода внутри основного сервера. Если бинарник зависает, превышает лимиты или выводит некорректный JSON, задача завершается состоянием RUN_ERROR.

При успешном завершении stdout рассматривается как JSON-документ метрик. Сервер преобразует его во внутреннюю структуру, сохраняет метрики в PostgreSQL и формирует HTML-отчёт с графиками. Сам отчёт выгружается в MinIO, а в базе остаётся только ключ объекта. Это уменьшает размер строк таблицы и упрощает повторную выдачу отчёта пользователю.

Заключение

Архитектура виртуальной лаборатории ориентирована на учебный веб-сценарий, в котором пользовательский код должен запускаться удобно, воспроизводимо и контролируемо. Для этого синхронный HTTP-запрос отделён от долгого выполнения через очередь задач, а результаты сохраняются в форме метрик и HTML-отчётов.

Предложенное решение сочетает веб-интерфейс, очередь на базе PostgreSQL, объектное хранилище MinIO и многоуровневый запуск пользовательского C/C++ кода. Такая архитектура может быть расширена новыми алгоритмами, наборами нагрузок, ролями преподавателя и автоматической проверкой решений студентов.

Список литературы

  1. 1. Docker Inc. Docker Documentation. URL: https://docs.docker.com/ (дата обращения: 13.06.2026).
  2. 2. JetBrains. Ktor Documentation. URL: https://ktor.io/docs/ (дата обращения: 13.06.2026).
  3. 3. MinIO. S3 Compatible Object Storage. URL: https://min.io/ (дата обращения: 13.06.2026).
  4. 4. PostgreSQL Global Development Group. PostgreSQL Documentation: SELECT, Locking Clause, SKIP LOCKED. URL: https://www.postgresql.org/docs/current/sql-select.html (дата обращения: 13.06.2026).
  5. 5. The Linux man-pages project. seccomp(2) — Linux manual page. URL: https://man7.org/linux/man-pages/man2/seccomp.2.html (дата обращения: 13.06.2026).
Справка о публикации и препринт статьи
предоставляется сразу после оплаты
Прием материалов
c по
Остался последний день
Размещение электронной версии
Загрузка материалов в elibrary
Публикация за 24 часа
Узнать подробнее
Акция
Cкидка 20% на размещение статьи, начиная со второй
Бонусная программа
Узнать подробнее