В прошлой серии: вход в суровый мир энтерпрайз архитектуры лежит через панель. То, что мертво, умереть не может, а посему в задании меня попросили отрефлексировать над диаграммой легаси и предложить перерождение. Но чтоб было веселей – минимум информации и всего четыре часа времени.
Некая недосказанность всегда присутствует на первых свиданиях. Жаль, что в этот раз она в плоскости тех.задания. Когда времени мало – проще танцевать от требований и ограничений, а не заниматься подтверждением парадокса выбора. Поэтому будем сразу говорить об архитектуре. На собеседованиях только и разговоров, что об архитектуре и о дизайне. Там говорят о том, как чертовски здорово наблюдать за огромным монолитным легаси, как он тает в волнах.
Чтоб утонуть в море возможностей, начнём с определения условий.
Догадки и додадки:
Система не занимается управлением и приёмом потоков, а только обработкой успешно законченных сессий. Задача стриминга, очереди ожидания, правильности и доступности исходных данных уже не наша проблема. Так же можно отсеять проблемы чтения. Если запись поступила на обработку – значит она без повреждений и доступна. (В реальном проектировании так и разделяют подсистемы – не надо тащить конвертацию форматов изображения и улучшения качества картинки в модуль распознавания текста. Делают конвейер отдельных модулей и медиатор. Например, микросервисы с ESB)
Все сессии идут с участием оператора и в систему одновременно не поступает записей больше числа операторов. А значит у нас не может быть непредсказуемой взрывной нагрузки из-за потока клиентов. Всё по теории ограничений. В данном случае нам не нужна пропускная способность больше, чем осилят принять операторы. Мы можем сразу высчитать максимальную возможную нагрузку на систему. Из необходимых данных у нас отсутствует еще размер/длинна сессии с оператором. Если минимально значимая сессия у нас 30 секунд и есть 100 операторов, то получать наша легаси система может максимум 200 вызовов в минуту с пиком в 100 за раз. Стоит учесть и выхлоп системы – вызовы API, но об этом дальше.
Вызовы API не блокируют систему. В идеале, конечно, мы совсем не хотим ждать ответа и хотелось бы просто куда-то постучаться и получить код 200 (не путать с грузом). Но если я правильно определил, что это точка интеграции, то значит API – это внешние системы и мы не можем управлять тем, как они работают. На том конце может быть бодрый и отдохнувший REST, а может и мыльный SOAP. В случае более тяжелых систем и железок можно готовиться к TCP/UPD. Поэтому я заранее предлагаю быть готовым обсудить это, но по возможности убрать из проблем легаси, а значит и сэкономить нервы на следующем этапе. Легитимным предположением будет, что внешняя система получает данные и даёт ACK (подтверждение) в ответ. Заниматься обработкой данных она будет потом. Ну, а судя по диаграмме, в которой внешних игроков нет – какого-то особого результата нам от нее вообще не надо. Вот на этом невысказанном предположении и держится весь хрупкий механизм интеграции.
Категоризатор обрабатывает все записи с полными метаданными, проводя их через все категории. Условный набор правил для вызова API не пропускает ничего. Раз нам известно, что он срабатывает по таймеру и обрабатывает всё, что доступно – мы рассматриваем легаси как проход по всему списку без всяких ухищрений с фильтрацией и поиском.
Запись, которая прошла все обработчики, переходит в архив сразу после категоризации. То есть полная категоризация происходит только один раз и только после всех мета процессоров. Это, видимо, сейчас решается тупо таймером. Сначала ждём все обработчики, а потом размечаем категории.
Каждый обработчик (Processing Engine) работает независимо. Значит они не учитывают результатов других обработчиков и не конкурируют за саму запись. Можно даже уточнить, что каждый получает свою копию. Опять-таки сводим легаси к проходу по списку, без графа зависимостей, вхождение в ступор (deadlock) и бесконечных циклов.
Репозиторий служит лишь для хранения и предоставления доступа к записям и мета-данным. CRUD. Мы не хотим, чтоб в хранилище были бизнес функции. Всякие процедуры, триггеры и тд. На оригинальной схеме не было исходящего соединения из репозитория, но на всякий случай не будем предполагать, и что входящие выполняют вызовы функции.
Клиент всегда работает с одной и той же копией системы (instance). Скорее всего система вообще устанавливается и работает локально у каждого из клиентов компании. Но SaaS - уже не новость, идея то родилась на вебе и хостингах. Вполне возможно, что мелкие клиенты работают с дата центром компании. Диаграмма не противоречит идее просто поднять всё на виртуалках в облаке. Lift & Shift - дорого, неэффективно, быстро. В таком случае хотелось бы, чтоб клиента не кидало от репы к репе как внучку и Жучку. Тем самым не усложняло нам жизнь с требованием запускать API только раз.
Предварительный итог:
Не совсем понятно, что изображают блоки в диаграмме – отдельно стоящие сервисы или модули внутри монолита. Я предполагаю, что это набор монолитов. Менеджер процессинга и обработчики – один большой камень, а категоризатор – другой. Каждый из них имеет свой интерфейс (UI/API/CLI), таймер (scheduler), конфигуратор и обработчик ошибок и базу данных. Хостят это где-то локально у клиента и, возможно, в своём дата центре. На облачную инфраструктуру явно не тянет. Все оптимистичные предположения можно смазать свежевыжитым маслом лести: "Я уверен, что раз продукт популярный, то тут у вас все грамотно спроектированно, и я представляю себе вот такой вариант..."
В чём цимес существующей системы:
Лёгкая развёртка и мониторинг. Установить и обслуживать 4-5 процессов намного легче чем 200. С расчётом на подержанных и доступных сисадминов, а не трендовых дорогих девопсов.
Односторонняя связь – монолиты слабо зависимы и теоретически не должны влиять друг на друга как в процессе разработки, так и работы. Распараллеливание даёт возможность для масштабирования большими блоками как горизонтально (scale out) так и вертикально (scale up).
Если нет multitenancy, то завезти будет относительно не сложно. Могут быть накладки с отсутствующими идентификаторами клиентов и потенциально отсутствующего сбрасывания состояния. Необходимо, чтобы базовые компоненты работали stateless и не возникало накладок с разной конфигурацией и доступом у разных клиентов.
Исходя из предыдущих пунктов, вполне осуществимо сделать пошаговую миграцию в новую систему. Шаги, конечно, будут Гуливерские, но всё же можно надеяться на малую кровь хрустящих под ногами human resources.
Высокая согласованность (consistency) данных. Один репозиторий – один источник правды (single source of truth). Удобно проверять и сохранять. Облегчает и обслуживание, и восстановление (disaster recovery).
Высокая приватность данных. Если всё у клиента, то он хозяин и данных, и железа. Отлично подходит всем гос. структурам и корпорациям - мечта офицеров и офисов с шапочками из фольги.
Дом тысячи кастомизаций. Раз у клиента не квартира в муравейнике, а хоть и типовой, но всё же свой дом, то и уровень извращений, которые он может себе в этом доме позволить – ограничен лишь деньгами и бандажом бюрократической фантазии.
Грабли:
С большим контролем приходит большая ответственность (с) Человек-Админ. Да, за всей инфраструктурой, как железом, так и софтом, клиент ухаживает сам. В меру своих возможностей, а не требований, как в случае с SaaS/PaaS.
Управление ресурсами. Большие компоненты в мире дискретной нагрузки требуют постоянно держать ресурсы для обработки потенциального максимума. Если у нас в пике 100 записей в секунду, а в среднем 10, то всё равно ресурс (физическое или виртуальное железо) надо неизменно иметь на 100.
Зависимости. В теории и на картинке монолиты не зависят друг от друга, но на самом деле вся система – распределённый монолит, сшитый одним бизнес-процессом и контрактами. Обработчики пишут мету, на которой основывается категоризатор. Ввод новых данных потребует изменения и там, и там. Даже на уровне тайминга мы видим зависимость – категоризатор бежит намного реже менеджера обработки, так как должен сработать после.
Общий ресурс. Как мы и сказали, категоризация идёт на основе метаданных, которые пишут обработчики. А значит оба модуля читают и пишут в ту же запись. И так как общего контроллера у них нет, а работают они параллельно, то у нас классический race condition.
Избыточные операции. Уже на уровне дизайна нам сказали, что категоризатор вынужден обрабатывать запись несколько раз. В худшем случае очень много раз (с возвращением без учета порядка). Судя по одной единственной стрелке между менеджером обработчиков и самими обработчиками – у нас блокирующий вызов и менеджер ждёт полного ответа. Еще одна косвенная улика, что там монолит без коммуникации либо плохая архитектура.
Низкая целостность процессов, в отличии от данных. У данных один источник, а процесс поделён на части. Если один из обработчиков постоянно падает, то категоризатор об этом не знает и возможно будет ждать и возвращаться к обработке записи вечно. Общий процесс и состояние процесса не известно. Особо стоит обратить, что отсутствующий результат обработчика может быть как ошибкой/падением, так и приемлемым поведением. Такие вот процессоры Шредингера.
Много точек полного отказа (fragility). Каждый блок незаменим (single point of failure), и падение/остановка влияют на весь процесс. Судя по диаграмме, там нет разделения очередей. Если репозиторий не доступен – всё лежит. И даже не переваривает уже проглоченное. Но если он доступен, а упал процессор, мало того, что клиент не получит вызовы интеграции, то у нас ещё и сработает эффект плотины. Мы рассчитывали на 100 запросов в секунду, но репа накапливает записи и как только процессор вернётся, но у него и категоризации будет бесконечный поток. Слава богу, что процессор сам управляет своими задачами, а значит не утонет. Но SLA интеграции и сервисы на той стороне может затопить. Так что плотина у вас, а прорвать может у клиента.
Проблема масштабируемости/производительности (performance). Если процессинг явно можно распараллелить и выделить каждый в отдельный сервис без сохранения состояния (stateless), то вот категоризатор так не выглядит. В текущей архитектуре – это единый блок, который видит и делает всё. Да, и по заданию его трогать нельзя, но это уже само по себе проблема. О ней стоит заявить и учесть в новом дизайне.
Ограниченная пропускная способность (throughput). Это боль скорее всего самая головная из всех головных у бизнеса. Если учесть, что процессоры метаданных не всегда возвращают ответ и работают несколько минут, то скорее всего мы ждём впустую часть времени. Это предположение строится на том, что в диаграмме таймер Х < У. И (вы же понимаете, что предложение должно было начаться с этой буквы?) если начнём подставлять цифры и прикинем, что максимальное время обработки 5 минут, и таймер обработки тоже 5 минут, то логичный таймер категоризации будет 6 минут. Получается, что в случае, если у нас сессия с оператором меньше 6 минут, то система будет всегда в догоняющем режиме. А значит не способна давать полезный выхлоп 24/7. Иными словами, для нагруженного бизнеса нужно больше, чем одна система. Типа в течение дня работаем на системе 1, а ночью дообрабатываем, но работаем в системе 2. Чтоб дорабатывать в 2 днём. Сомневаюсь, что клиенты рады active-passive масштабированию по системе близнецов Диоскуров.
Вывод:
С одной стороны времени в презентации мало, но очень важно показать, что вы учли и знаете многое. Озвучивать всё нужно тезисно и уверено. Так как бы это сделал Карлсон. Не оставляя места сомнениям и вопросам. А вот расписать можно подробней, если есть время. После панельки вас попросят прислать презентацию и настоящий отсев претендентов пойдёт, когда выступят все. А там уже могут уделить отдельное внимание содержанию. Возможно, в приемной комиссии будут и люди, не участвовавшие в этом интервью, но очень желающие «всех посмотреть». Очень важно упомянуть про плюсы легаси архитектуры. Вам же сказали, что продукт успешный, так что своё φ высказать стоит, зайдя с комплиментов. Не стоит указывать в списке минусов неразрешимые проблемы либо то, что вы не смогли/захотели исправить в новом подходе. Разложить грабли надо так, что их можно было обойти. Вот тот самый exactly once – ну его на XOR.
Ответ на первые два вопроса готов. В общей презентации из 9 слайдов: 3 из них мишура (Титульный лист, Об авторе, Thank You!), 2 в этой статье, ещё 3 будут содержанием следующей.
Приглашение на собеседование и задание | |
Ответ на вопросы по легаси | |
Новый дизайн и финал |