Проекты
Конкурсные проекты

Разработка информационно-аналитической системы для исследования производительности и отказоустойчивости программных систем в зависимости от архитектурных решений и протоколов обмена сообщениями


Тип участника:  Физическое лицо
Полное наименование организации/физического лица/авторского или творческого коллектива:  Алексенко Алексей Викторович
Идея и краткое описание ИТ-проекта: 

1. Идея ИТ-проекта

Проект направлен на комплексное исследование производительности и отказоустойчивости веб-сервисов в зависимости от архитектурных подходов. Для этого создаётся информационно-аналитическая платформа, автоматизирующая полный цикл испытаний – от генерации нагрузки до сбора и визуализации метрик. Основная идея – сравнить классическую синхронную архитектуру с несколькими современными асинхронными подходами (реактивными, корутинными, виртуальными потоками) в одинаковых условиях, собрать количественные показатели (пропускная способность, задержки, ошибки) и выяснить, как архитектура влияют на эти ключевые метрики. Таким образом, проект должен дать практические данные о влиянии архитектурных решений (модель “один поток на запрос” vs. неблокирующие модели, Project Loom, корутины и пр.) на быстродействие системы и её способность выдерживать высокую нагрузку без отказов.

2. Краткое описание ИТ-проекта

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

  • Веб-приложение (сервис) на базе Spring Boot, реализующее REST API для домена PetClinic (управление данными о владельцах питомцев, визитах к ветеринару и т.п.). Оно спроектировано по многослойной архитектуре (контроллеры, сервисы, репозитории, сущности) и может запускаться в разных конфигурациях (см. ниже).

  • Средства нагрузочного тестирования: инструмент k6 используется для генерации HTTP-нагрузки по заданному сценарию и проверки корректности ответов сервиса. Нагрузочное тестирование проводится автоматически, имитируя постепенный рост числа виртуальных пользователей вплоть до тысячи и более, что позволяет довести систему до предела производительности.

  • Система мониторинга: сервис экспонирует метрики (через Spring Boot Actuator), которые собираются Prometheus’ом и отображаются в Grafana в режиме реального времени. Это позволяет наблюдать ключевые показатели (RPS, латентность, использование ресурсов и пр.) во время тестов.

  • Инфраструктура развёртывания: все компоненты (приложение, PostgreSQL, Prometheus, Grafana) контейнеризованы с помощью Docker и объединены Docker Compose-файлом. Благодаря этому развернуть тестовый стенд можно одной командой, что упрощает повторяемость экспериментов.

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

Перечень решаемых задач: 

3. Перечень решаемых задач

Для достижения цели дипломного проекта был решён следующий круг задач:

  • Анализ предметной области и технологий. Изучены существующие подходы к построению высоконагруженных сервисов: классическая блокирующая модель Servlet/JDBC, неблокирующая реактивная модель (WebFlux/Reactor), сопрограммы (Kotlin Coroutines), виртуальные потоки Project Loom и механизмы отказоустойчивости (backpressure, пулы потоков и соединений и т.д.). Это обеспечило теоретическую базу для экспериментов.

  • Проектирование системы испытаний. Спроектирована архитектура информационно-аналитической платформы: выбрана предметная область (PetClinic) для типового CRUD-приложения, определён набор архитектурных конфигураций сервиса для сравнения, разработана схема развёртывания (отдельно сервис, СУБД, мониторинг) и план испытаний (метрики, сценарии нагрузок, критерии отказоустойчивости).

  • Реализация нескольких версий сервиса. Разработано само веб-приложение с возможностью переключения архитектурных профилей. Реализованы все слои приложения (контроллеры, бизнес-логика, доступ к данным) единообразно для корректного сравнения, а различия заключаются во внедрении разных технологий обработки запросов и доступа к БД. Всего подготовлено 7 конфигураций сервиса: синхронная (Spring MVC + JDBC), синхронная с виртуальными потоками (MVC + JDBC + Loom), реактивная (Spring WebFlux + JDBC на Netty), реактивная с виртуальными потоками (WebFlux + JDBC + Loom), реактивная с корутинами (WebFlux + JDBC + Kotlin Coroutines), полностью реактивная (WebFlux + R2DBC), реактивная с R2DBC и корутинами. Также заложена возможность работы на разных серверных контейнерах (Tomcat, Jetty, Undertow для servlet-моделей и Netty для WebFlux).

  • Настройка окружения и инфраструктуры. Настроена база данных PostgreSQL с фиксированным размером пула соединений (8), что стало общим ограничением для всех тестов. С помощью Liquibase автоматизировано создание схемы и начальное заполнение БД, чтобы каждый запуск начинался в консистентном состоянии (таблицы PetClinic и тестовые данные). Все сервисы объединены с БД и мониторингом в Docker Compose для единообразной среды тестирования. Настроен непрерывный интеграционный конвейер (GitHub Actions) для автоматической сборки проекта и прогонки unit-тестов при каждом изменении кода.

  • Разработка сценариев нагрузочного тестирования. Созданы скрипты k6, моделирующие реальную работу пользователей: последовательность из нескольких разных запросов (POST, GET, PUT, DELETE, health-check), повторяемая каждым виртуальным пользователем. Сценарий предусматривает постепенное наращивание количества одновременных пользователей (ramping) вплоть до точки насыщения ресурсов, что позволяет за один прогон определить максимальную пропускную способность и поведение системы на пределе нагрузки. В сценарии заложены проверки корректности (ассерты) на ответы сервиса, чтобы отслеживать процент ошибок.

  • Проведение серии экспериментов и сбор метрик. Для каждой конфигурации сервиса проведён полный прогон нагрузочного теста (~12 минут) вплоть до максимума нагрузки. Собраны метрики: throughput (RPS), latency (средняя, медиана, перцентили p90/p95/p99), использование ресурсов (активные потоки, использование пула соединений, CPU, память) и процент ошибок. Метрики собирались как средствами k6 (RPS, ошибки, латентность), так и Prometheus (системные метрики, нагрузка на JVM и БД).

  • Анализ результатов и выводы. Обработаны полученные данные: построены сравнительные графики, сводные таблицы результатов для разных подходов. Выполнен анализ, включающий обсуждение, почему те или иные архитектуры показали определённые результаты, выявлены узкие места (например, пул соединений к БД оказался лимитирующим фактором) и сформулированы выводы о целесообразности применения технологий в разных условиях.

Таким образом, проект решает задачи по созданию экспериментальной платформы, проведению нагрузочных испытаний и получению новых знаний о влиянии архитектурных решений на качество программных систем.

Описание функциональных возможностей и элементов проекта: 

4. Описание функциональных возможностей и элементов проекта

Функциональная структура разработанной системы включает несколько ключевых компонентов и возможностей:

  • Многовариантный CRUD-сервис. Основой является веб-приложение (тестируемый сервис) для управления данными "клиники домашних животных" (PetClinic). Функционально оно предоставляет REST API для операций создания, чтения, обновления и удаления сущностей (Owner, Pet, Visit, Vet и др.). Реализована полноценная бизнес-логика (например, регистрация нового питомца, назначение визита и т.д.) на сервисном слое, и доступ к PostgreSQL базе данных через слой репозиториев. Важно: логика работы для пользователя везде одинакова – различаются только внутренние механизмы обработки (потоки, реактивность и т.д.), что позволяет сравнивать производительность без влияния различий в функционале.

  • Переключаемые архитектурные профили. Проектом реализована возможность запускать сервис в разных архитектурных режимах, управляемых Spring-профилями и модулями Maven. Всего подготовлено семь конфигураций:

    1. Spring MVC + JDBC – классический блокирующий стек (1 поток на запрос, синхронный JDBC-драйвер).

    2. Spring MVC + JDBC + Loom – тот же стек, но с использованием виртуальных потоков Project Loom для обработки запросов (позволяет сравнить эффект Loom при блокирующей модели).

    3. Spring WebFlux + JDBC (Reactor) – реактивный неблокирующий веб-слой (Reactor Netty) при блокирующем JDBC-доступе к БД.

    4. Spring WebFlux + JDBC + Loom – реактивный веб-слой, где блокирующие обращения к JDBC выполняются во виртуальных потоках (комбинация Loom с реактивным подходом).

    5. Spring WebFlux + JDBC + Kotlin Coroutines – реактивный веб-слой, логика контроллеров/сервисов написана с использованием корутин Kotlin (suspend-функции), которые внутри выполняют JDBC-вызовы.

    6. Spring WebFlux + R2DBC (Reactor) – полностью неблокирующий стек: реактивный веб-слой и реактивный драйвер базы данных R2DBC вместо JDBC.

    7. Spring WebFlux + R2DBC + Kotlin Coroutines – аналогичный полностью реактивный сценарий, но описание взаимодействия выполнено с помощью корутин (R2DBC драйвер обёрнут в Coroutine API, возвращающий Flow и suspend-результаты).

    Переключение между профилями осуществляется через переменные окружения SPRING_PROFILES_ACTIVE или разные исполняемые артефакты. Например, для запуска варианта WebFlux + R2DBC + Loom достаточно указать SPRING_PROFILES_ACTIVE=webflux,r2dbc,loom. Такая гибкость заложена в архитектуру приложения и обеспечена конфигурацией Spring Boot.

  • Поддержка разных серверных контейнеров. Сервис может работать на различных платформах сервлет-контейнеров: Tomcat (по умолчанию в Spring Boot), Jetty, Undertow, а также на реактивном сервере Netty для WebFlux. В проекте настроены отдельные модули/профили, позволяющие запуск на Jetty и Undertow для сравнения их влияния на производительность. Например, синхронный MVC-тест проводился на Tomcat, Jetty и Undertow; для WebFlux-тестов сравнивались Netty (родной для WebFlux) и альтернативные реактивные адаптеры на базе сервлет-контейнеров. Эти возможности расширяют эксперимент, позволяя оценить влияние web-сервера: в таблице 4.1 приведены результаты для всех трёх серверов и Netty.

  • База данных и миграции. Для хранения данных используется PostgreSQL (вер. 15). СУБД развернута в отдельном Docker-контейнере; схема данных соответствует доменной модели PetClinic. Применён инструмент миграций Liquibase, что автоматизирует создание/обновление схемы при запуске сервиса. Каждое испытание начинается с гарантированно корректной структуры БД и необходимых справочных данных (например, список специальностей ветеринаров), что обеспечило воспроизводимость тестов. Пул соединений к БД фиксирован размером 8 во всех конфигурациях – это ключевое условие эксперимента, уравнивающее возможности разных подходов по доступу к базе (ни одному не позволено открыть более 8 параллельных запросов к БД). Тем самым сравнение сосредоточено на оверхедах приложений, а не на различии числа соединений.

  • Нагрузочное тестирование (генератор нагрузки). В состав платформы входит модуль нагрузочного тестирования на базе инструмента k6. Разработаны сценарии на JavaScript (для k6), моделирующие последовательность действий пользователя: создание сущности, несколько чтений, обновление, удаление, проверка health-check. Каждый виртуальный пользователь циклично выполняет эту транзакцию из ~11 запросов. Сценарий настроен по стратегии ramping arrival rate: постепенное увеличение числа одновременных пользователей (шагами, каждые N секунд добавляется новая порция VU) от 0 до заданного максимума (например, 3000 виртуальных пользователей). Это позволяет нагружать систему вплоть до насыщения ресурсов и фиксировать момент, когда она перестаёт справляться с возрастанием нагрузки. K6 отслеживает время ответа каждого запроса, агрегирует метрики RPS, а также проводит проверки корректности ответов (HTTP-коды, содержание JSON) на каждом шаге. Если ответы не соответствуют ожиданиям, тест считает их ошибочными. Во всех проведённых тестах процент ошибок оставался крайне низким – не более 0,01% запросов завершались с ошибкой, то есть сервисы даже при пиковых нагрузках не “падали” и практически все запросы обслуживались успешно. Это свидетельствует об отказоустойчивости всех рассмотренных реализаций по критерию непрерывности работы под нагрузкой.

  • Сбор и визуализация метрик. Важной функцией платформы является мониторинг производительности в реальном времени. В сервис внедрён Spring Boot Actuator, экспонирующий технические метрики (количество запросов, загрузка CPU, размер пула, количество потоков, heap memory и др.) по HTTP в формате, совместимом с Prometheus. Параллельно с запуском теста поднимается сервер Prometheus, который опрашивает метрики приложения с нужной периодичностью. Также собираются системные метрики окружения (например, утилизация процессора, потребление памяти контейнером). Данные из Prometheus отображаются в Grafana – в Docker Compose включён экземпляр Grafana с настроенным дашбордом, где в ходе теста можно наблюдать графики RPS, latency (включая перцентили), статус здоровья приложения и т.п.. Эта функциональность позволяет глубже понимать поведение каждой конфигурации: например, видеть рост очереди на подключение к БД или увеличение количества потоков при Loom. После завершения теста все метрики за период испытания сохраняются, и на их основе строятся итоговые сравнительные графики (включены в отчёт).

  • Автотесты и CI/CD. Помимо нагрузочного тестирования, проект включает и функциональные тесты: написаны модульные и интеграционные тесты (JUnit 5 + Spring Boot Test) для проверки корректности работы репозиториев и контроллеров в разных профилях. Они выполняются при каждой сборке. В репозитории настроен GitHub Actions workflow, который при каждом push запускает сборку Maven, миграции БД в тестовом контейнере и прогон всех JUnit-тестов. Таким образом, поддерживается непрерывная интеграция – это повышает надёжность разработки (новые изменения не нарушают существующую функциональность). Хотя CI/CD не является основной "функцией" для конечного пользователя, для самого проекта это важный элемент надежности и поддерживаемости.

Дата внедрения (в случае, если предполагается запуск проекта в эксплуатацию):  -
Используемые платформы, средства разработки: 

5. Используемые платформы и средства разработки

Ниже перечислены основные технологии, фреймворки и инструменты, применённые в проекте, с указанием их ролей:


Технология / Инструмент Роль в проекте
Java 21 (OpenJDK) Основной язык и платформа разработки. Используются современные возможности Java 21, включая превью-функцию виртуальных потоков Project Loom. Код приложения частично написан на Kotlin (для корутин), что совместимо с JVM.
Spring Boot 3.2 Каркас для создания приложения. Обеспечивает автоконфигурацию, встроенный веб-сервер и удобное управление зависимостями. Позволил легко переключать профили (MVC/WebFlux, JDBC/R2DBC и пр.) и собрать приложение в единый исполняемый JAR.
Spring Web MVC (Spring MVC) Модуль Spring для реализации традиционного Servlet-стека. Используется в профиле mvc для построения REST-контроллеров и обработки запросов по схеме «один поток на запрос».
Spring WebFlux (Project Reactor) Реактивный веб-фреймворк Spring, использующий неблокирующую обработку запросов (на основе Netty) и реактивные типы Flux/Mono. Применяется в профиле webflux для неблокирующих контроллеров и сервисов. Reactor автоматически управляет потоками (event-loop) и backpressure.
Kotlin Coroutines Технология сопрограмм в языке Kotlin. Использована в одном из вариантов реализации: контроллеры и сервисы определены как suspend-функции, позволяющие писать асинхронный код в императивном стиле. Библиотека kotlinx-coroutines-reactor обеспечивает интеграцию корутин с Reactor (для совместимости с WebFlux).
Project Loom (Virtual Threads) Новая модель лёгких потоков в Java. Задействована в конфигурациях с профилем loom для замены потоков ОС виртуальными потоками при обработке запросов и выполнении JDBC-операций. Позволяет потенциально запускать тысячи параллельных задач без значимых overhead потоков ОС.
Spring Data JPA + Hibernate Стек для доступа к данным в синхронных профилях. Spring Data JPA позволяет определять интерфейсы-репозитории, а Hibernate обеспечивает ORM-мэппинг и выполнение SQL-запросов. В профиле jdbc приложение использует JPA репозитории для работы с PostgreSQL через JDBC-драйвер.
Spring Data R2DBC Аналогичный стек доступа к данным для реактивных профилей. Spring Data R2DBC предоставляет ReactiveCrudRepository/DatabaseClient, позволяющие не блокировать потоки при взаимодействии с БД. Применяется в профиле r2dbc – вместо Hibernate используется драйвер R2DBC для PostgreSQL.
PostgreSQL 15 СУБД для хранения данных приложения. Выбрана как современная открытая реляционная СУБД с поддержкой ACID-транзакций, индексов, JSON-полей и др.. Развёрнута в контейнере; тестовая база содержала несколько тысяч записей (наследие PetClinic) и работала с пулом из 8 соединений.
Liquibase Инструмент для управления схемой БД. Использован для автоматического применения миграций при запуске приложения – создаёт таблицы сущностей PetClinic и заполняет первоначальные справочники (например, виды питомцев). Это обеспечивает одинаковую структуру БД на каждом тестовом прогоне.
Jackson Библиотека для сериализации/десериализации JSON. Неявно используется Spring Boot (Starter Web) для преобразования объектов доменной модели и DTO в JSON-ответы и обратно (при приёме запросов). Таким образом, API приложения обменивается данными в формате JSON.
Bean Validation (JSR 380) Спецификация валидации данных. В проекте применяются аннотации (@NotNull, @Size и др.) на полях DTO и сущностей для проверки корректности входных данных. Spring автоматически проверяет их при получении запросов; в случае нарушения ограничений возвращается ошибка 400 с описанием.
JUnit 5 + Spring Boot Test Фреймворки модульного тестирования. Написан набор unit-тестов и интеграционных тестов контроллеров/репозиториев, которые запускаются при сборке Maven. Используется SpringBootTest для поднятия контекста и H2 в памяти (либо Testcontainers PostgreSQL) в тестах, что позволяет увериться в работоспособности приложения в различных профилях.
GitHub Actions (CI) Сервис непрерывной интеграции, настроенный для проекта. Файл workflow запускает сборку, прогон тестов и проверку стиля кода на каждом коммите. Это помогло обеспечить стабильность разработки и повторяемость сборок.
Docker & Docker Compose Средства контейнеризации. Каждый компонент (приложение, база, Prometheus, Grafana) упакован в Docker-образ. Docker Compose позволяет одним командным (docker-compose up) развернуть все контейнеры, настроив их сеть и тома. Это существенно упростило деплой тестового стенда и переносимость системы между разными машинами.
k6 (Load Testing Tool) Инструмент для генерации нагрузки и измерения производительности. Сценарии k6 написаны на JS и входят в репозиторий (например, script.js). k6 постепенно увеличивает число виртуальных пользователей, отправляя HTTP-запросы к сервису, и собирает статистику по каждому этапу (включая распределение времени ответа). Также проверяет корректность ответов (assertions).
Prometheus + Grafana Стек мониторинга. Prometheus настроен на периодический опрос метрик Spring Boot Actuator (по HTTP) и на сбор системных метрик хоста. Grafana подключена к базе Prometheus и отображает дашборд с графиками RPS, latency (включая перцентили p95/p99), количеством потоков, соединений к БД и др. в режиме реального времени. Это позволило отслеживать поведение системы под нагрузкой и впоследствии проанализировать собранные временные ряды.
Инструменты профилирования (JFR, JMX) Для глубокой диагностики использовались средства профилирования JVM (Java Flight Recorder) и JMX-консоли. Например, снимались дампы потоков во время тестов (для сравнения количества активных потоков при Loom vs без Loom), отслеживались JMX-метрики пула соединений (число ожидающих запросов). Эти данные дополняли картину и помогали объяснить результаты.




Все применённые технологии являются свободно распространяемыми или открытыми (Open Source), что снизило издержки на разработку. Использование новейшей версии Spring Boot и JDK гарантировало актуальность платформы и поддержку требуемых функций (например, виртуальных потоков).

Стоимость разработки системы:  0
Средний размер ежегодных затрат на эксплуатацию:  0
Перспективы развития: 

Проект обладает хорошим заделом для дальнейшего развития. Перспективы развития информационно-аналитической системы можно разделить на несколько направлений:

  • Расширение сценариев испытаний. В текущей работе тестировался монолитный CRUD-сервис с одной базой данных и сравнительно простой бизнес-логикой. В дальнейшем можно добавить другие типы нагрузок и сценариев: например, имитировать более сложные бизнес-транзакции, добавить фоновые задачи, очереди сообщений, или протестировать поведение при чередовании периодов нагрузки и спокойствия. Также возможно испытание системы на других профилях нагрузки (например, постоянная высокая нагрузка vs. резкие всплески) и с разными объемами данных в БД.

  • Добавление новых архитектурных паттернов. Перспективно интегрировать в платформу испытания паттернов отказоустойчивости, таких как Circuit Breaker, Bulkhead, Retry и т.п., которые используются в микросервисах для повышения устойчивости. Это позволило бы исследовать не только “сырые” архитектуры, но и готовые решения для улучшения надежности. Также можно включить в сравнение другие подходы: например, фреймворки Quarkus или Vert.x для реактивности, использование Grpc или других протоколов вместо REST, сравнение монолита с микросервисной архитектурой и оркестрацией запросов между сервисами.

  • **Тестирование масштабируемости. В продолжение работы возможно развернуть несколько экземпляров сервисов и проверить горизонтальное масштабирование (scale-out) различных подходов. Например, распределить нагрузку на кластер из нескольких узлов и измерить, как линейно растёт производительность разных архитектур при добавлении новых инстансов. Это приблизит эксперимент к реалистичным условиям облачных развертываний и покажет, есть ли различия между подходами в контексте масштабирования вширь.

  • Повышение уровня автоматизации и аналитики. Можно встроить более автоматизированный анализ результатов: например, после каждого тестового прогона автоматически генерировать отчёт (графики, статистика) и выводить рекомендации. Интеграция с CI/CD может быть расширена до автоматического прогона бенчмарков при изменении кода (регрессное тестирование производительности). Кроме того, перспективно добавить модуль, автоматически подбирающий конфигурации (например, размер пула, объем памяти JVM) и определяющий оптимальные параметры для каждой архитектуры.

  • Обновление технологий. По мере развития платформы Java и Spring можно включать новые версии и сравнивать улучшения. Например, если выйдет стабильная версия Loom (не превью) или новые оптимизации в R2DBC/JDBC драйверах, платформа позволит быстро их протестировать. Также можно добавить поддержку других СУБД (NoSQL хранилищ) или NewSQL решений, чтобы оценить влияние не только архитектуры приложения, но и типа хранилища.

Автор работы прямо указывает, что разработанная платформа и полученные экспериментальные данные дают возможность осознанного выбора архитектуры для новых проектов. Инженеры могут опираться на метрики и выводы данного исследования, чтобы понимать компромиссы каждого подхода и выбирать решение, наиболее подходящее под их требования – максимум ли производительности, минимизация задержек, экономия ресурсов или соответствие реактивной экосистеме. Это делает систему полезной и после завершения проекта, а ее развитие (добавление новых экспериментов) может продолжить приносить пользу профессиональному сообществу. Фактически, платформа может эволюционировать в универсальный инструмент для бенчмаркинга и профилирования веб-сервисов.

Достижение поставленных целей: 

9. Достижение поставленных целей, завершённость проекта

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

Главный результат – получены количественные метрики и проведено сравнение различных архитектурных подходов на практике. Это позволило сформировать выводы о производительности и надежности каждого. Кратко итоги эксперимента следующие:

  • Классическая синхронная архитектура (Spring MVC + JDBC) показала наивысшую производительность в условиях данного теста. На сервере Tomcat она достигала ~3830 запросов/с при 95%-перцентиле задержки ~0,77 с. Это лучше, чем у всех асинхронных конкурентов. Фактически, при ограничении на стороне базы данных (пул 8 соединений) традиционный подход не вносит лишних накладных расходов и полностью выжимает возможности БД. С точки зрения отказоустойчивости, MVC-сервис корректно выдержал максимальную нагрузку, хотя для обработки тысяч одновременных соединений ему пришлось создать очень много потоков ОС.

  • Полностью реактивный стек (Spring WebFlux + R2DBC), напротив, продемонстрировал наименьший throughput – порядка 1600–1800 req/s, а задержки p95 выросли до ~2,5 секунд. Это говорит о том, что в текущей реализации реактивный драйвер PostgreSQL уступает по скорости оптимизированному JDBC. Выигрыша от перехода на R2DBC в монолитном CRUD-сервисе не получено – более того, производительность снизилась. Таким образом, цель "сразу получить выигрыш от реактивности" не оправдалась. Тем не менее, сервис на R2DBC тоже был устойчив к перегрузке (ошибок практически не было), просто обслуживал запросы медленнее.

  • Промежуточные результаты показали гибридные подходы: WebFlux + JDBC (Reactor) и WebFlux + JDBC (Kotlin coroutines) смогли достичь ~70–80% от throughput MVC (до ~3000 req/s), при повышении задержек в 1.5–2 раза (p95 ~1,2–1,5 с). Небольшое снижение скорости объясняется накладными расходами на асинхронную координацию (планирование задач, переключение контекстов). Однако оба варианта работали стабильно, без лавинообразного роста ошибок или отказов вплоть до предельной нагрузки. Интересно, что корутинная реализация по эффективности почти не уступала чисто реактивной на Reactor. То есть, при правильном использовании, Kotlin Coroutines могут дать аналогичный результат, что и Reactor, сохраняя более понятный императивный код – это важный практический вывод.

  • Project Loom (виртуальные потоки) в контексте нашего случая (блокирующая БД) не дал прироста производительности. В конфигурации MVC + Loom throughput даже слегка снизился по сравнению с обычными потоками (~3160 vs 3830 req/s на Tomcat), а хвостовые задержки p99 ухудшились. Причина выяснена: тысячи виртуальных потоков конкурировали за 8 соединений к базе, образуя длинную очередь ожидания. Loom позволил создать существенно больше параллельных запросов, но это привело лишь к росту времени ожидания в очереди, не увеличивая реальную пропускную способность (т.к. пределом была БД). Этот вывод подчёркивает, что эффект новых технологий зависит от узкого места: если узкое место – база данных, то просто увеличив число потоков (пусть даже виртуальных) ситуацию не улучшить. Loom, впрочем, упростил разработку (не нужно вручную управлять пулом потоков), и в других сценариях с множеством источников I/O мог бы показать плюсы, но в нашем монолите с одной БД пользы не принёс.

  • Отказоустойчивость и поведение при перегрузке. Ни один из протестированных подходов не потерпел катастрофического отказа при экстремальной нагрузке: сервисы продолжали работать, отвечая на запросы, хоть и с разной скоростью. Процент ошибок во всех случаях был ~0%, система не "рушилась". Однако формы деградации различались: у реактивных сервисов при перегрузке росли латентности (но система сама регулировала прием новых запросов благодаря backpressure), у синхронного – вырастала очередь входящих запросов на уровне сервлет-контейнера. В целом, можно заключить, что все варианты архитектур продемонстрировали достаточную надёжность в том смысле, что выдержали нагрузку без падений. Разница была именно в производительности и эффективности использования ресурсов под нагрузкой.

В итоге, проект не только выполнил поставленные цели, но и предоставил конкретные рекомендации: например, в условиях монолита с ограниченным подключением к БД классический подход остаётся конкурентоспособным, а переход на реактивность оправдан больше ради горизонтальной масштабируемости и экономии ресурсов, чем ради мгновенного роста throughput. Все результаты и выводы подробно задокументированы в пояснительной записке, цели работы достигнуты полностью.

Актуальность, экономическая или социальная полезность: 

13. Актуальность, экономическая или социальная полезность

Актуальность темы проекта не вызывает сомнений. В современном мире веб-приложения сталкиваются с постоянно растущими нагрузками, и выбор архитектурных решений напрямую влияет на способность системы масштабироваться и оставаться надёжной. Появление новых моделей конкурентности (реактивное программирование, корутины, виртуальные потоки) ставит перед инженерами вопрос: стоит ли переходить на них, какой отдачи ожидать? На момент 2025 года Project Loom только готовится выйти из превью, реактивные стеки активно продвигаются, но мало практических сравнений с классическим подходом. Дипломная работа отвечает на этот запрос времени – она предоставляет свежие данные и анализ того, что действительно дают новые технологии в контексте типового бизнес-приложения. Это ценно для отрасли, так как помогает принимать обоснованные решения (не руководствуясь только hype). По сути, проект служит мостиком между теорией и практикой современного высоконагруженного backend-разработки.

Экономическая полезность проекта проявляется в возможности оптимизации ресурсов. Например, из выводов работы следует, что если узким местом является база данных, то использование сложных асинхронных технологий не даст выигрыша. Значит, компания может сэкономить время (а значит, деньги), не внедряя неоправданно сложный реактивный стек там, где хватит хорошо настроенного классического решения. С другой стороны, показано, что неблокирующие подходы потребляют меньше потоков и памяти, что важно при развертывании множества сервисов – на ограниченной инфраструктуре реактивные сервисы смогут выдержать больше соединений, не падая по ресурсам. Это тоже экономический эффект: более эффективное использование оборудования, потенциально меньше затрат на сервера/виртуальные машины при переходе на реактивную модель (в случае большого количества одновременно подключенных клиентов). Таким образом, результаты исследования могут привести к снижению затрат на инфраструктуру или, по крайней мере, предотвратить неоправданные траты на внедрение технологий “ради моды”.

Социальная полезность проявляется в улучшении качества ИТ-сервисов для конечных пользователей. Производительность и отказоустойчивость напрямую влияют на пользовательский опыт: быстрый отклик и отсутствие сбоев – ключ к удовлетворённости пользователей. Проект, способствуя выбору оптимальной архитектуры, косвенно помогает строить более надёжные и масштабируемые сервисы (например, в электронном здравоохранении, онлайн-образовании, госуслугах и т.д.). Чем надёжнее системы, тем меньше социальных рисков (срывов важных онлайн-сервисов) и выше доверие к цифровым сервисам.

Кроме того, актуальность для научного сообщества: тема лежит на стыке программной инженерии и системного программирования. Работа актуальна как практическим инженерам, так и исследователям, занимающимся производительностью – она предоставляет методику проведения подобных сравнений, которую могут перенять другие.

Отдельно отметим, что проект продвигает культуру измерения и доказательного подхода в разработке ПО. Вместо голословных заявлений “реактивный быстрее”, автор предлагает проверить и измерить. Это очень полезно с точки зрения образования новых специалистов (проект выполнялся в университете).

Резюмируя: актуальность дипломного проекта высока, поскольку он отвечает на современные вопросы о выборе технологий для высоконагруженных систем. Полезность – и экономическая (рационализация затрат на технологии, оптимизация ресурсов) и социальная (улучшение качества цифровых сервисов через повышение их быстродействия и надёжности).

Адаптивность, стилистическое единство всех функциональных блоков: 

16. Адаптивность и стилистическое единство (не применимо)

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

Адаптивность обычно относится к фронтенд-разработке (чтобы сайт хорошо смотрелся и на мобильном, и на десктопе). Здесь же API вызывается программно; результаты смотрятся либо в текстовых логах/таблицах, либо на дашборде Grafana. Grafana сама по себе имеет веб-интерфейс, но это готовый инструмент, его дизайн – не часть дипломного проекта. То есть автор не проектировал ни макеты, ни CSS – и, соответственно, не решал задачу адаптивности.

Стилистическое единство – про то, чтобы все страницы и элементы интерфейса выглядели целостно, в едином стиле. В нашем случае UI-страниц просто нет. Единство можно разве что упомянуть в контексте кода (стили кодирования) – и тут можно отметить, что код выдержан в едином стиле (Kotlin + Java, соблюдены соглашения Spring), но это слишком уход в сторону.

Проще говоря, пункты 14–16 не применимы, потому что проект – не про веб-дизайн. Отсутствие адаптивного дизайна не является недостатком, это сознательный выбор, так как он не требовался. Диплом нацелен на исследование производительности, а не на разработку интерфейса. Соответственно, адаптивность и стилистическое единство фронтенда здесь не оцениваются.

Масштабируемость, способность к взаимодействию с другими системами, мобильность: 

10. Масштабируемость, способность к взаимодействию с другими системами, мобильность

Масштабируемость. Разработанная система ориентирована на исследование масштабируемости различных подходов и сама по себе построена с учётом масштабирования. Во-первых, приложение может быть запущено в нескольких экземплярах (контейнерах) параллельно, обслуживая увеличенный поток запросов – реактивные и coroutine-варианты для этого особенно хорошо подходят, так как используют меньше потоков и эффективнее расходуют CPU/память при большом числе соединений. В тестах было показано, что синхронный MVC хоть и достиг максимальной производительности на одном узле, делает это ценой тысячи потоков, что в реальной среде может приводить к проблемам памяти и контекстных переключений. Неблокирующие же решения потребляют на порядок меньше потоков (десятки вместо тысяч) и лучше подходят для горизонтального масштабирования и работы в контейнеризированных средах с ограниченными ресурсами. Таким образом, сама архитектура проекта масштабируема: можно увеличивать нагрузку, добавляя узлы, а встроенные механизмы (например, Actuator/Prometheus) позволят отслеживать, как линейно растёт производительность.

Взаимодействие с другими системами. Проект изначально построен на открытых стандартах, что облегчает интеграцию. Сервис предоставляет RESTful API (JSON/HTTP), что позволяет внешним системам вызывать его как обычный веб-сервис. Более того, поддержка OpenAPI/Swagger упрощает генерацию клиентов для этого API (в репозитории есть openapi.yml для PetClinic REST API). Также сервис интегрирован с Prometheus, что означает, что его метрики могут быть легко встроены в общую систему мониторинга организации. Логи сервисов выводятся в стандартный вывод и могут перенаправляться в централизованные системы логирования (ELK, Graylog и т.п.). Контейнеризация через Docker делает систему независимой от окружения: её можно запускать в различных облачных платформах или оркестраторах (Kubernetes) без изменений. Например, Docker-образ приложения может быть размещён в регистре и развернут совместно с другими микросервисами. В целом, архитектура соответствует принципам 12-factor app, что облегчает взаимодействие с другими компонентами. Проект не предполагает тесной интеграции с какими-то проприетарными системами, но по необходимости к сервису можно прикрепить внешние модули (кеширующий слой Redis, сервис авторизации, и др.) с минимальными изменениями, благодаря слабой связности компонентов.

Мобильность. В классическом понимании мобильности (поддержка мобильных устройств или переносимость) проект не нацелен на мобильные клиентские приложения – у сервиса нет пользовательского интерфейса, только API. Однако если трактовать “мобильность” как портативность и гибкость развертывания, то система обладает высокой мобильностью. Все функциональные блоки унифицированы и контейнеризованы, поэтому могут быть быстро перенесены на новый сервер или в облако (достаточно наличия Docker). Например, разработчик может на своём ноутбуке запустить тот же набор контейнеров, что и на тестовом сервере, и получить идентичный стенд. Это важно для воспроизводимости результатов и совместной работы. Также, сервис можно считать облачно-агностичным: он не привязан к конкретным PaaS-сервисам и может работать повсеместно, где есть Java-машина или Docker. Совместимость версий обеспечивается использованием стандартных средств Spring – приложение будет работать под любой JVM 17+ (для Loom нужен 21, но этот профиль неактивен по умолчанию) и с любой совместимой СУБД (PostgreSQL легко заменить на, например, MySQL, изменив драйвер).

Подводя итог, масштабируемость и интеграция – сильная сторона проекта: он исследует эти качества на уровне приложения и сам построен модульно и стандартизированно. “Мобильность” в плане переносимости решения также на высоте благодаря Docker. Напротив, поддержки мобильных клиентских платформ (Android/iOS) здесь не предполагается, так как проект – сугубо серверный. Но при желании, можно легко создать мобильное приложение, обращающееся к разработанному API, поскольку API документирован и стабилен.

Обоснованность применяемых проектных решений: 

12. Обоснованность применяемых проектных решений

Все ключевые проектные решения в работе тщательно обоснованы, опираясь на требования эксперимента и лучшие практики разработки:

  • Выбор предметной области (CRUD на PetClinic). Обоснование: нужен типовой сценарий, близкий к реальным бизнес-приложениям, но достаточно простой для реализации нескольких вариантов. PetClinic – известный пример, охватывающий CRUD-операции, связи между сущностями, валидатор и т.д. Его использование позволило не тратить время на выдумывание домена, а сразу получить реалистичную нагрузку (операции с базой, отношения многие-ко-многим и пр.). При этом бизнес-логика достаточно проста, чтобы не влиять на производительность непредсказуемо. Этот выбор оправдан и тем, что Spring PetClinic имеет готовую модель данных и даже образцы кода, что ускорило разработку.

  • Многослойная архитектура приложения. Автор реализовал сервис в классическом разделении на контроллеры, сервисы, репозитории, сущности. Обоснование: слабая связанность и высокая модульность. Благодаря этому легко менять реализацию доступа к данным или веб-слоя, не трогая остальной код. Например, реализация на R2DBC потребовала других репозиториев, но контроллеры и сервисы остались прежними – такой дизайн упростил внедрение разных технологий. Кроме того, слои с IoC-контейнером Spring делают систему расширяемой: можно в будущем заменить PostgreSQL на другую БД, или добавить кеш, и это затронет только нижний слой. Также, слои соответствуют рекомендациям Spring Framework, что повышает надёжность решений (проверенная временем структура).

  • Использование Spring Boot и профилей. Обоснование: Spring Boot 3 даёт современную основу с поддержкой и MVC, и WebFlux, и корутин, а также готовую интеграцию с Actuator, Liquibase, Prometheus. Выбор Spring Boot позволил сократить время конфигурирования (автоконфигурация) и сосредоточиться на логике. Профили Spring – удобный механизм, чтобы в одном приложении держать несколько вариаций. Например, профиль loom включает LoomAutoConfiguration, подменяющую Executors на виртуальные потоки; профиль r2dbc переключает бины репозиториев на ReactiveCrudRepository и т.д. Альтернативой могло бы быть создание отдельных проектов под каждую конфигурацию, но профили намного экономичнее и обеспечивают единую кодовую базу. Это обосновано желанием сравнивать архитектуры в максимально идентичном коде. Решение дополняется Maven-модулями (tomcat/jetty/undertow), чтобы отдельно собрать исполняемый JAR с нужным контейнером – так обеспечено удобство тестирования разных серверов без ручной перекомпоновки зависимостей.

  • Ограничение пула соединений к БД (8 соединений). Это проектное решение обосновано тем, что нужно привести разные модели к общему знаменателю. Если бы реактивному приложению позволить 100 соединений, а синхронному оставить 8, сравнение было бы некорректным – реактивный мог бы выдать больше throughput просто за счёт параллелизма на уровне БД. Здесь же автор намеренно сделал лимит одинаковым, чтобы посмотреть, какие накладные расходы несут сами фреймворки. 8 соединений – достаточно мало, чтобы создать конкуренцию между запросами, но достаточно для насыщения одного сервиса. Этот выбор опирается на то, что узким местом станет именно приложение, а не база (что и произошло). Данное решение оправдано и успешно себя показало – все подходы уткнулись в предел ~3000–3800 RPS, близкий к тому, что 8 соединений PostgreSQL могут обработать.

  • Выбор метрик и подход к нагрузке. Автор решил фокусироваться на RPS и перцентилях времени отклика (p95, p99), а не только на среднем времени. Обоснование: высокие перцентили показывают tail latency, важную для пользователя (опыт показал, что некоторые подходы давали низкий средний отклик, но высокий p99 – Loom на пределе дал большой разброс задержек). Также измерялся процент ошибок – ведь отказоустойчивость определена как способность не допускать большого роста ошибок. Такой набор метрик покрывает и производительность, и надёжность. Сценарий нагрузки с постепенным ростом VU выбран для выявления точки насыщения плавно, а длительность теста ~12 минут – чтобы система “прогрелась” и вышла на плато. Все эти решения (что и как измерять, как нагружать) обоснованы стандартными практиками нагрузочного тестирования и целями исследования.

  • Интеграция Prometheus/Grafana. Хотя можно было собирать метрики только средствами k6, принято решение добавить полноценный мониторинг. Обоснование: получить внутреннюю телеметрию приложения – количество потоков, состояние пула соединений, использование CPU/памяти и т.п. Без этого было бы сложнее объяснить наблюдаемые эффекты. Например, с помощью метрик автор увидел, что при Loom количество активных потоков взлетело до тысяч, а при Reactor оставалось десятки – отсюда выводы о нагрузке на планировщик ОС. Решение включить Grafana позволило наглядно видеть поведение в реальном времени и быстро реагировать (например, замечать аномалии). Это оправдано с точки зрения методологии эксперимента – повысило достоверность интерпретации результатов. Тем более, настройка этих инструментов в Docker Compose заняла относительно мало усилий, а пользу принесла существенную.

  • Прочие решения. Использование Docker – обосновано требованием портативности и единообразия среды (исключить влияния “чужой” среды). Выбор JUnit и GitHub Actions – стандарт для обеспечения качества кода; проект научный, но автор позаботился о надёжности внедряемых изменений, что придаёт уверенности в корректности результатов (например, автоматические тесты ловили бы логические ошибки). Логирование через SLF4J/Logback – обосновано необходимостью отладки и потенциального аудита; настроено на консоль для простоты, но можно перенастроить, что гибко.

В целом, каждое существенное решение (от технологии до параметров теста) в пояснительной записке либо напрямую обосновано, либо следует из логики эксперимента. Проектные решения соответствуют поставленным задачам исследования, и автор явно стремился минимизировать искажающие факторы, выбирая консервативные и проверенные подходы в том, что не является предметом эксперимента (например, взят PostgreSQL, а не менее известная БД; взят PetClinic, а не придумывался экзотический кейс). Это говорит об обдуманности и обоснованности всех решений.

Оригинальность, новизна, отличие от аналогов либо отсутствие аналогов: 

11. Оригинальность, новизна, отличие от аналогов

Данный проект обладает значительной новизной, особенно с учётом времени его выполнения (2024–2025 гг). Оригинальность проявилась в следующем:

  • Комплексное сравнение новейших технологий. Проект объединяет в одном тестовом стенде сразу несколько современных подходов, включая Project Loom (виртуальные потоки в Java, на момент работы ещё в статусе превью) и Kotlin Coroutines – технологии, которые только набирают популярность и мало исследованы в прикладных сравнениях. На момент начала работы реальные кейсы сравнения Loom vs Reactor практически отсутствовали в публичном доступе, что делает эксперимент уникальным. Аналогично, сравнение Reactor и корутин в рамках Spring WebFlux тоже достаточно ново – оба подхода конкурирующие и мало было данных, насколько они различаются на практике. Таким образом, исследование заполнит пробел в знаниях о влиянии этих технологий на производительность (до работы эффект многих из них был неочевиден и требовал проверки).

  • Единые условия для разных подходов. В отличие от разрозненных бенчмарков, которые можно найти в блогах или статьях, здесь все архитектурные версии реализованы в рамках одного приложения, с одинаковой логикой и под одинаковой нагрузкой. Это устраняет массу переменных (разные домены, разные реализации), которые обычно мешают прямому сравнению. Например, автор не взял готовые цифры из разных источников, а сам реализовал каждый вариант и прогнал его на одном оборудовании, с одной БД, с одним сценарием теста – такая чистота эксперимента встречается редко. Аналоги (если искать) – это академические статьи, сравнивающие, например, async vs threads, но там часто рассматриваются упрощённые задачи. Здесь же взято полнофункциональное приложение (PetClinic) и реально эмулирована работа пользователей, что добавляет ценности и новизны результатам.

  • Автоматизация и полнота цикла. Проект не ограничился написанием нескольких версий сервиса – была создана целая платформа, включающая мониторинг, сбор метрик, Docker-окружение, CI. Такой всеобъемлющий подход, приближенный к боевому окружению, выгодно отличает работу. По сути, автор построил мини-лабораторию производительности, которую можно повторно использовать для других экспериментов. Это отличается от типичных дипломных проектов, где часто делают только прототип без инфраструктуры. Здесь же большое внимание уделено DevOps-практикам, что тоже ново в учебных работах.

  • Отсутствие прямых аналогов. На момент разработки проекта не было известных открытых решений, которые позволяли бы нажатием одной кнопки развернуть систему и протестировать Spring MVC vs WebFlux vs Loom vs Coroutines. Конечно, существуют отдельные демо-проекты для каждого из этих технологий, но единая информационно-аналитическая система, агрегирующая их сравнение – это авторская идея. Можно сказать, что аналогов в открытом доступе нет: проект получился уникальным сочетанием технологий и методики испытаний.

  • Научная новизна результатов. Полученные результаты сами по себе оригинальны, поскольку дают свежий взгляд на эффективность R2DBC (оказалось медленнее JDBC в нашем случае), на полезность Loom (не принес улучшения при узком месте в БД) и показывают, что грамотная реализация важнее выбора между Reactor и корутинами. Эти выводы представляют интерес для сообщества разработчиков высоконагруженных систем и дополняют существующие знания. В отчёте они сопоставляются с ожиданиями и теорией, что подчёркивает научную составляющую работы.

Таким образом, новизна проекта заключается как в самом подходе (создание универсальной платформы для экспериментов), так и в полученных данных. От существующих решений проект отличается своей всеобъемлющей природой и фокусом на сравнительном анализе современных технологий в равных условиях. Можно считать, что дипломная работа имеет элемент исследовательского вклада, а не только инженерной реализации.

Соответствие дизайн-решения целевой аудитории: 

15. Соответствие дизайн-решения целевой аудитории (не применимо)

Этот критерий также относится к веб-дизайну и UX, подразумевая оценку того, насколько визуальное оформление и взаимодействие соответствуют ожиданиям целевой аудитории. В данном проекте отсутствует какое-либо дизайн-решение интерфейса, поскольку конечным "пользователем" системы является либо разработчик, либо сама система (CI, скрипты тестирования). Целевая аудитория проекта – инженеры и исследователи, которые используют полученные данные, а не широкие массы пользователей, взаимодействующие с UI.

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

Можно сказать, что дизайн архитектуры (а не UI) соответствует своей "аудитории" – разработчикам, которые ожидают модульности, читабельности кода, стандартных подходов Spring. Здесь требования аудитории разработчиков учтены (проект структурирован понятно, код основан на Spring PetClinic – знакомом примере). Однако это выход за рамки понятия "дизайн-решение" в смысле UI/UX.

В итоге, критерий соответствия дизайн-решений целевой аудитории не применим к данному проекту. Приложение не имеет визуального дизайна, который нужно было бы подстраивать под аудиторию. Все решения касались технической архитектуры, а они оценивались по другим параметрам (производительность, масштабируемость и т.д.), а не по восприятию аудиторией.

Юзабилити и полезность: 

14. Юзабилити и полезность (не применимо)

Данный пункт относится к параметрам веб-дизайна и оценки пользовательского интерфейса, однако дипломный проект не имеет пользовательского интерфейса вовсе. Сервис, разработанный в рамках проекта, предоставляет только REST API и предназначен для автоматизированного сбора метрик, а не для прямого взаимодействия с конечным пользователем.

Показатель юзабилити обычно характеризует удобство использования интерфейса человеком – навигацию, дизайн экранов, понятность элементов и т.п. В нашем же случае отсутствует графический интерфейс или фронтенд: как указано в описании, backend-проект не содержит UI (интерфейса), он реализует только APIGitHub. Поэтому говорить о юзабилити в привычном смысле некорректно.

Тем не менее, можно условно оценить "юзабилити" для разработчиков или пользователей платформы (то есть удобство эксплуатации самой системы тестирования): здесь проект показывает себя положительно, т.к. развертывается одной командой, документация (Swagger/OpenAPI) доступна, результаты визуализируются на понятных графиках Grafana. То есть, система удобна в использовании специалистами, но опять же, это не юзабилити интерфейса для массового пользователя, а удобство инструментария.

В контексте требований задания, пункт про юзабилити не применяется, потому что проект не является продуктом веб-дизайна или пользовательским приложением. Его полезность проявляется в другом – в качестве инженерного инструмента – что описано в других пунктах (актуальность, полезность). Таким образом, критерий юзабилити для UI здесь можно опустить, чтобы не притягивать несуществующие характеристики.

Гарантирую достоверность предоставленной в заявке информации. Подтверждаю, что организация не находится в состоянии ликвидации, банкротства, реорганизации (Только для организаций):  Да
Презентация проекта pdf:  Загрузить
Возврат к списку
нет доступа к комментариям Авторизоваться