18 января 2023

Из практики: строим архитектурное решение для системы хранения и просмотра файлов

В последние два-три года активно обсуждается профессия IT-архитектора. С переходом многих бизнесов в онлайн потребность в этих специалистах сильно выросла. В 2022 году даже был опубликован профстандарт 06.003 «Архитектор программного обеспечения». Среди основных функций специалиста выделены:

  • Выявление и согласование требований к программной системе с точки зрения архитектуры
  • Выбор и моделирование архитектурного решения для реализации программной системы

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

Краткое техническое задание

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

  • Функциональные требования: определяют действия, которые должна выполнять система. Описанием функциональных требований обычно занимается аналитик. На их основе готовится техническое задание.
  • Атрибуты качества: определяют свойства, которые должна демонстрировать система. Чаще всего сюда входят нефункциональные требования, например, производительность, масштабируемость, доступность и т.п. Уточнение этих требований и построение системы с их учетом – основная задача архитектора.
  • Ограничения: дополнительные требования, которые необходимо соблюдать, но напрямую они не относятся к поведению системы. Сюда могут входить ограничения ко времени и бюджету, используемым технологиям и т.п. Их также необходимо учитывать при проектировании системы.

Учет всех перечисленных архитектурно-значимых требований и построение системы на их основе требует умений и навыков по проведению анализа задачи и ранжирования требований, выделения наиболее значимых из них. Разработчик часто не обладает такими навыками – его основная задача состоит в реализации системы по готовым требованиям. Технической квалификации и кругозора аналитика также может быть недостаточно для принятия таких решений. Именно здесь и выходит на первый план роль IT-архитектора. Он должен учесть все требования, подобрать необходимый архитектурный стиль, описать архитектурный каркас будущей системы и заложить его основы реализации.

Итак, задача – построить систему хранения и просмотра файлов в формате PDF. Этот пример носит учебный характер, его основная цель – показать, в чем состоит работа архитектора.

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

Функциональные:

  • пользователь может загружать в систему файлы в одном из популярных форматов;
  • перед сохранением файл должен конвертироваться в формат PDF;
  • пользователь может скачивать и просматривать любые файлы, загруженные кем-либо в систему.

Нефункциональные:

  • отсутствие ограничений по количеству хранимых файлов и времени их хранения;
  • приемлемая скорость загрузки файла;
  • ограничение размера файла – 128 Мб;
  • высокая скорость скачивания файлов для просмотра из любой точки мира;
  • потеря загруженного файла не допускается;
  • вывод из строя одного из оборудования не должно приводить к отказу системы.

Решение архитектурной задачи

Одно из первых действий после знакомства с ТЗ – выделить объекты данных, которые участвуют в системе. Анализ их структуры и предъявляемых к ним требований поможет на первом этапе определить рамки системы и ограничить перечень архитектурных паттернов при проектировании системы. Исходя из ТЗ, основные объекты системы – пользователь и файл.

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

Объект «файл» представляет собой именованную бинарную последовательность. Ключевым моментом здесь является размер объекта. Файлы постоянно будут добавляться и они могут быть совершенно разного размера. Это значит, что, во-первых, нужно предусмотреть расширяемость объёма хранилища данных. Во-вторых, заложить необходимую пропускную способность сети, чтобы обеспечить требование высокой скорости скачивания.

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

Определившись с объектами данных и учитывая требования к системе, на основе анализа задания можно сделать набросок схемы будущей архитектуры ПО.

Рис. 1

Рис. 1

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

Далее заложим возможность горизонтального масштабирования сервиса, т.е. увеличения его производительности за счёт распределения нагрузки между имеющимся и новыми серверами, запуская на них необходимое количество инстансов сервиса. Это позволит оперативно реагировать на возрастающую нагрузку в будущем (см. рис. 2).

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

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

Рис. 2

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

Рис. 3

Эта схема (рис.3) уже похожа на готовый шаблон проектирования Command and Query Responsibility Segregation (CQRS). Он как раз предназначен для разделения ответственности между операциями чтения и записи по отношению к хранилищу данных. Подробнее – тут.

Чтобы наше решение больше соответствовало CQRS, необходимо отвязать эти сервисы от одного хранилища данных. Сделать это можно путём добавления реплики к хранилищу: настроить сервис выгрузки так, чтобы он читал только с неё, а сервис загрузки записывал бы только в основное хранилище.

Рис. 4

Архитектура, изображенная на рис. 4, добавляет следующие преимущества:

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

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

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

Рис. 5.png

Рис. 5

Эта схема отражает последние улучшения архитектуры системы. Многие преимущества, описанные ранее, действуют и для подобного разделения сервисов. Но важно ещё раз отметить, что при таком подходе пользователю не нужно ждать завершения конвертации файла. Этот процесс работает независимо от сервиса загрузки файла.

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

Рис. 6.png

Рис. 6

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

Рис. 7.png

Рис. 7

На рис. 7 доработано еще несколько моментов:

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

Результат

На этом примере мы показали, как проектируется архитектурное решение для разработки системы хранения и просмотра файлов в формате PDF, в котором:

  • учтены все функциональные и нефункциональные требования, особенности используемых данных;
  • предусмотрено горизонтальное масштабирование системы, возможность её распределения по различным дата-центрам, географически отдалённым друг от друга.

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

Антон / Андрей
Руководитель архитектурного комитета SimbirSoft / Архитектор SimbirSoft
Понравилась статья?
Подпишитесь на рассылку SimbirSoft! Пришлём письма о лайфхаках в разработке, поделимся опытом управления командами и компанией, а также расскажем о новых ивентах SimbirSoft.
Антон / Андрей
Руководитель архитектурного комитета SimbirSoft / Архитектор SimbirSoft

Другие статьи

Алгоритмы машинного обучения в сервисах для исследования генеалогии
30 января 2023
Автоматизировать — нельзя действовать по старинке
19 января 2023
SimbirSoft – в списках самых надежных поставщиков ИТ-услуг
10 января 2023
Написать нам
Оставьте контакты, чтобы обсудить проект и условия
сотрудничества, или позвоните: 8 800 200-99-24
Оставьте свои контакты
SimbirSoft регулярно расширяет штат сотрудников.
Отправьте контакты, чтобы обсудить условия сотрудничества.
Порекомендуйте друга — получите вознаграждение!
  • Python-разработчик
  • Java-разработчик
  • Node.js-разработчик
  • Системный аналитик
  • DevOps-инженер
  • Специалист тендерного отдела
  • Менеджер по привлечению клиентов
  • 1С-консультант
  • Data Engineer
  • Java-архитектор
  • 1С-архитектор
  • Data Scientist
Прикрепить резюме, до 10Мб
Файл выбран