Пробы на роль Архитектора: наступление

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

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

Knockin' on Heaven's Door : на берегу архитектуры

Knockin' on Heaven’s Door: на берегу архитектуры

Чтоб утонуть в море возможностей, начнём с определения условий.

Догадки и додадки:

  1. Система не занимается управлением и приёмом потоков, а только обработкой успешно законченных сессий. Задача стриминга, очереди ожидания, правильности и доступности исходных данных уже не наша проблема. Так же можно отсеять проблемы чтения. Если запись поступила на обработку — значит она без повреждений и доступна. (В реальном проектировании так и разделяют подсистемы — не надо тащить конвертацию форматов изображения и улучшения качества картинки в модуль распознавания текста. Делают конвейер отдельных модулей и медиатор. Например, микросервисы с ESB)

  2. Все сессии идут с участием оператора и в систему одновременно не поступает записей больше числа операторов. А значит у нас не может быть непредсказуемой взрывной нагрузки из-за потока клиентов. Всё по теории ограничений. В данном случае нам не нужна пропускная способность больше, чем осилят принять операторы. Мы можем сразу высчитать максимальную возможную нагрузку на систему. Из необходимых данных у нас отсутствует еще размер/длинна сессии с оператором. Если минимально значимая сессия у нас 30 секунд и есть 100 операторов, то получать наша легаси система может максимум 200 вызовов в минуту с пиком в 100 за раз. Стоит учесть и выхлоп системы — вызовы API, но об этом дальше.

  3. Вызовы API не блокируют систему. В идеале, конечно, мы совсем не хотим ждать ответа и хотелось бы просто куда-то постучаться и получить код 200 (не путать с грузом). Но если я правильно определил, что это точка интеграции, то значит API — это внешние системы и мы не можем управлять как они работают. На том конце может быть бодрый и отдохнувший REST, а может и мыльный SOAP. В случае более тяжелых систем и железок можно готовиться к TCP/UPD. Поэтому я заранее предлагаю быть готовым обсудить это, но по возможности убрать из проблем легаси, а значит и сэкономить нервы на следующем этапе. Легитимным предположением будет, что внешняя система получает данные и даёт ACK (подтверждение) в ответ. Заниматься обработкой данных она будет потом. Ну, а судя по диаграмме, в которой внешних игроков нет — какого-то особого результата нам от нее вообще не надо. Вот на этом невысказанном предположении и держится весь хрупкий механизм интеграции.

  4. Категризатор обрабатывает все записи с полными метаданными, проводя их через все категории. Условный набор правил для вызова API не пропускает ничего. Раз нам известно, что он срабатывает по таймеру и обрабатывает всё, что доступно — мы рассматриваем легаси как проход по всему списку без всяких ухищрений с фильтрацией и поиском.

  5. Запись, которая прошла, все обработчики переходит в архив сразу после категоризации.  То есть полная категоризация происходит только один раз и только после всех мета процессоров. Это, видимо, сейчас решается тупо таймером. Сначала ждём всех обработчики, а потом размечаем категории.

  6. Каждый обработчик (Processing Engine) работает независимо. Значит они не учитывают результатов других обработчиков и не конкурируют за саму запись. Можно даже уточнить, что каждый получает свою копию. Опять-таки сводим легаси к проходу по списку, без графа зависимостей, вхождение в ступор (deadlock) и бесконечных циклов.

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

  8. Клиент всегда работает с одной и той же установкой системой (instance). Скорее всего система вообще устанавливается и работает локально у каждого из клиентов компании. Но SaaS — уже не новость, идея то родилась на вебе и хостингах. Вполне возможно, что мелкие клиенты работают с дата центром компании. Диаграмма не противоречит идее просто поднять всё на виртуалках в облаке. Lift & Shift — дорого, неэффективно, быстро. В таком случае хотелось бы, чтоб клиента не кидало от репы к репе как внучку и Жучку. Тем самым не усложняло нам жизнь с требованием запускать API только раз.

Предварительный итог:

Не совсем понятно, что изображают блоки в диаграмме — отдельно стоящие сервисы или модули внутри монолита. Я предполагаю, что это набор монолитов. Менеджер процессинга и обработчики — один большой камень, а категоризатор — другой. Каждый из них имеет свой интерфейс (UI/API/CLI), таймер (scheduler), конфигуратор и обработчик ошибок и базу данных. Хостят это где-то локально у клиента и, возможно, в своём дата центре. На облачную инфраструктуру явно не тянет. Все оптимистичные предположения можно смазать свежевыжитым маслом лести: «Я уверен, что раз продукт популярный, то тут у вас все грамотно спроектированно, и я представляю себе вот такой вариант…»

Legacy session processing: input stream->repository→processing engines→categorization→callout» /></p>

<p> Legacy session processing: input stream→repository→processing engines→categorization→callout </p>

<h4>В чём цимес существующей системы: </h4>

<ol><li><p>Лёгкая развёртка и мониторинг. Установить и обслуживать 4–5 процессов намного легче чем 200. С расчётом на подержанных и доступных сисадминов, а не трендовых дорогих девопсов.</p></li><li><p>Односторонняя связь — монолиты слабо зависимы и теоретически не должны влиять друг на друга как в процессе разработки, так и работы. Распараллеливание даёт возможность для масштабирования большими блоками как горизонтально (scale out) так и вертикально (scale up).</p></li><li><p>Если нет multitenancy, то завезти будет относительно не сложно. Могут быть накладки с отсутствующими идентификаторами клиентов и потенциально отсутствующего сбрасывания состояния. Необходимо, чтобы базовые компоненты работали stateless и не возникало накладок с разной конфигурацией и доступом у разных клиентов.</p></li><li><p>Исходя из предыдущих пунктов, вполне осуществимо сделать пошаговую миграцию в новую систему. Шаги, конечно, будут Гуливерские, но всё же можно надеяться на малую кровь хрустящих под ногами human resources.</p></li><li><p>Высокая согласованность (consistency) данных. Один репозиторий — один источник правды (single source of truth). Удобно проверять и сохранять. Облегчает и обслуживание, и восстановление (disaster recovery).</p></li><li><p>Высокая приватность данных. Если всё у клиента, то он хозяин и данных, и железа. Отлично подходит всем гос. структурам и корпорациям — мечта офицеров и офисов с шапочками из фольги.</p></li><li><p>Дом тысячи кастомизаций. Раз у клиента не квартира в муравейнике, а хоть и типовой, но всё же свой дом, то и уровень извращений, которые он может себе в этом доме позволить — ограничен лишь деньгами и бандажом бюрократической фантазии.</p></li></ol>

<h4>Грабли: </h4>

<ol><li><p>С большим контролем приходит большая ответственность © Человек-Админ. Да, за всей инфраструктурой, как железном, так и софтом, клиент ухаживает сам. В меру своих возможностей, а не требований, как в случае с SaaS/PaaS.</p></li><li><p>Управление ресурсами. Большие компоненты в мире дискретной нагрузки требуют постоянно держать ресурсов для обработки потенциального максимума. Если у нас в пике 100 записей в секунду, а в среднем 10, то всё равно ресурсы (физическое или виртуальное железо) надо неизменно иметь на 100.</p></li><li><p>Зависимости. В теории и на картинке монолиты не зависят друг от друга, но на самом деле вся система — распределённый монолит, сшитый одним бизнес-процессом и контрактами. Обработчики пишут мету, на которой основывается категоризатор. Ввод новых данных потребует изменения и там, и там.  Даже на уровне тайминга мы видим зависимость — категоризатор бежит намного реже менеджера обработки, так как должен сработать после.</p></li><li><p>Общий ресурс. Как мы и сказали, категоризация идёт на основе мета-данных, которые пишут обработчики. А значит оба модуля читают и пишут в ту же запись. И как как общего контроллера у них нет, а работают они параллельно, то у нас классический race condition.</p></li><li><p>Избыточные операции. Уже на уровне дизайна, нам сказали, что категоризатор вынужден обрабатывать запись несколько раз. В худшем случае очень много раз (с возвращением без учета порядка). Судя по одной единственной стрелке между менеджером обработчиков и самими обработчиками — у нас блокирующий вызов и менеджер ждёт полного ответа. Еще одна косвенная улика, что там монолит без коммуникации либо плохая архитектура.</p></li><li><p>Низкая целостность процессов, в отличии от данных. У данных один источник, а процесс поделён на части. Если один из обработчиков постоянно падает, то категоризатор об этом не знает и возможно будет ждать и возвращаться к обработке записи вечно. Общий процесс и состояние процесса не известно. Особо стоит обратить, что отсутствующий результат обработчика может быть как ошибкой/падением, так и приемлемым поведением. Такие вот процессоры Шредингера.  </p></li><li><p>Много точек полного отказа (fragility). Каждый блок не заменим (single point of failure), и падение/остановка влияют на весь процесс. Судя по диаграмме, там нет разделения очередей. Если репозиторий не доступен — всё лежит. И даже не переваривает уже проглоченное. Но если он доступен, а упал процессор, мало того, что клиент не получит вызовы интеграции, то у нас ещё и сработает эффект плотины. Мы рассчитывали на 100 запросов в секунду, но репа накапливает записи и как только процессор вернётся, но у него и категоризации будет бесконечный поток. Слава богу, что процессор сам управляет своими задачами, а значит не утонет. Но SLA интеграции и сервисы на той стороне может затопить. Так что плотина у вас, а прорвать может у клиента.</p></li><li><p>Проблема масштабируемости/производительности (performance). Если процессинг явно можно распараллелить и выделить каждый в отдельный сервис без сохранения состояния (stateless), то вот категоризатор так не выглядит. В текущей архитектуре — это единый блок, который видит и делает всё. Да, и по заданию его трогать нельзя, но это уже само по себе проблема. О ней стоит заявить и учесть в новом дизайне.</p></li><li><p>Ограниченная пропускная способность (throughput). Это боль скорее всего самая головная из всех головных у бизнеса. Если учесть, что процессоры мета-данных не всегда возвращают ответ и работают несколько минут, то скорее всего мы ждём впустую часть времени. Это предположение строиться на том, что в диаграмме таймер Х < У. И (вы же понимаете, что предложение должно было начаться с этой буквы?) если начнём подставлять цифры и прикинем, что максимальное время обработки 5 минут, и таймер обработки тоже 5 минут, то логичный таймер категоризации будет 6 минут. Получается, что в случае, если у нас сессия с оператором меньше 6 минут, то система будет всегда в догоняющем режиме. А значит не способна давать полезный выхлоп 24/7. Иными словами, для нагруженного бизнеса нужно больше, чем одна система. Типа в течение дня работаем на системе 1, а ночью дообрабатываем, но работаем в системе 2. Чтоб дорабатывать в 2 днём. Сомневаюсь, что клиенты рады active-passive масштабированию по системе близнецов Диоскуров.</p></li></ol>

<h4>Вывод: </h4>

<p>С одной стороны времени в презентации мало, но очень важно показать, что вы учли и знаете многое. Озвучивать всё нужно тезисно и уверено. Так как бы это сделал Карлсон. Не оставляя места сомнениям и вопросам. А вот расписать можно подробней, если есть время. После панельки вас попросят прислать презентацию и настоящий отсев претендентов пойдёт, когда выступят все. А там уже могут уделить отдельное внимание содержанию. Возможно, в приемной комиссии будут и люди, не участвовавшие в этом интервью, но очень желающие «всех посмотреть». Очень важно упомянуть про плюсы легаси архитектуры. Вам же сказали, что продукт успешный, так что своё φ высказать стоит, зайдя с комплиментов. Не стоит указывать в списке минусов неразрешимые проблемы либо то, что вы не смогли/захотели исправить в новом подходе. Разложить грабли надо так, что их можно было обойти. Вот тот самый exactly once — ну его на XOR.</p>

<p><img src=

Карлсон не оставляет места сомнениям и вопросам.

Ответ на первые два вопроса готов. В общей презентации из 9 слайдов: 3 из них мишура (Титульный лист, Об авторе, Thank You!), 2 в этой статье, ещё 3 будут содержанием следующей.

© Habrahabr.ru