Taking the "System Analysis" course.
- Week 1: event storming and data modeling
- Week 2: strategic DDD
- Week 3: stakeholders, characteristics, conditions and limitations
- Stakeholders research
- Choosing architecture style (context analysis)
- Found limitations and conditions
- Characteristics from the previous iteration (week 2)
- Characteristics found in the current iteration
- Characteristics - result
- Decomposition to services (subsystems)
- Choosing an architecture style and DB type for each service (subsystem)
- Choosing appropriate communication style and type
- Verification and fitness-functions
- Sample ADR
- Week 4: architecture rework planning
Сделайте event storming модель проекта.
Текстом опишите логику по которой сгруппировали команды и события в контексты.
Выделил три основных контекста, которые представляют из себя три последовательных этапа одного большого основного процесса:
- “Размещение заказа клиентом”
- “Сборка расходников для заказа”
- “Выполнение заказа”
Отдельно стоит контекст “Найм воркеров”, потому что он представляет из себя самостоятельный процесс, которые поставляет нам новых воркеров в основной процесс.
Отдельно стоит контекст “Аккаунтинг и биллинг”. Несмотря на то, что платится за услуги по смыслу “в конце” основного процесса, кажется логичным выделить аккаунтинг и биллинг в отдельный контекст из-за цикличности и повторяемости процессов внутри него, а так же из-за повышенной сложности процессов.
Отдельно стоит контекст “Контроль качества”. Несмотря на то, что процесс внутри этого контекста выглядит на данный момент скудно, в будущем может разрастись. Процесс внутри этого контекста уже выглядит весьма самодостаточно. Вижу его как бы “лисенером” над основным процессом, который впитывает в себя информацию и генерирует инсайты, которые могут привести к тюнингу основного процесса, побочных процессов или новым фичам в системе.
По похожим причинам, что и контекст “Контроль качества” выделил контексты “Ставки” и “Матчинг воркеров”.
Выделил несколько аспектных (технических?) контекстов:
- “identity management” контекст, т.к. данные о всех пользователях (клиенты, воркеры, менеджменты), взаимодейтсвующих с системой нужны практически везде.
- контекст “нотификаций”, т.к. слушает события других контекстов в системе и производит имейл нотификации.
Сделайте модель данных для требуемой системы
Сделайте общую модель всех полученных коммуникаций в системе
Выберете подходящую реализацию проекта (монолит или сервисы, как элементы системы связаны между собой).
Хочу выдержать баланс между двумя экстремами: монолит или микросервис per контекст.
Прихожу к выводу, что будут следующие компоненты:
- FE + BE для контекста “Размещение заказа клиентом”. BE реализовывает логику и выставляет API для FE, а FE служит для клиентов.
- BE для контекста “Метчинг воркеров”. Выношу отдельно, т.к. для алгоритма рано или поздно понадобится специфичный технологический стек.
- FE + BE для контекста “Найм воркеров”. FE отдельно для того, чтобы спрятать его за какой-нибудь anti-ddos слой.
- FE + BE для контекста “Сборка расходников”. BE реализовывает бизнес-логику и предоставляет API для FE, а FE служит для работников склада.
- FE + BE для контекста “Выполнение заказа”. BE реализовывает бизнес-логику и предоставляет API для FE, а FE служит для воркеров.
- Один общий BE для контекстов “Ставки на заказы” и “Контроль качества”, плюс общий FE для менеджмента. FE включает в себя функциональности ставок и контроля качества, плюс является entry-point’ом в других части системы, где возможны менеджмент-операции. Решил объединить BE для контекстов, с которыми взаимодействует только менеджмент, чтобы снизить Ops нагрузку.
- Отдельный BE для контекста “Аккаунтинг и биллинг”, т.к. в нем много интеграций с платежными системами и более сложная бизнес-логика, потому что завязана на деньгах. Будет предоставлять API, которое будет использоваться на разных FE (менеджментом для начисления денег воркерам, клиентами и воркерами для отображения инвойсов и т.д.)
- Отдельный сервис нотификаций, чтобы удобно было горизонтально скейлить при необходимости.
- Отдельный identity management, но тут требуется более точно проанализировать, для чего конкретно он существует. Есть подозрение, что это какое-то прокси в identity-мир родительской компании happy cat box.
Коммуникации между частями системы должны быть понятны из общей диаграммы коммуникаций в системе.
Выбор асинхронно/синхронно старался делать по следующему принципу:
- если в контексте необходимо явно среагировать на какое-то событие, то в этот контекст посылается доменное событие. (например, событие “добавлен новый воркер” посылается в “аккаунтинг и биллинг”)
- если в контексте необходимо иметь “под рукой” самые актуальные данные из другого контекста в большом объеме, то в этот контекст данные стримятся. (например, новые воркеры стримятся из “наем воркеров” в “метчинг воркеров на заказ”)
- если один контекст требует здесь и сейчас данные другого контекста в небольшом объеме, то этот контекст выполняет синхронный запрос на получение данных. (например, “размещение заказа клиентом” запрашивает размер скидки у “аккаунтинг и биллинг” при размещении заказа)
Синхронные коммуникации через REST HTTP, чтобы разрабам было проще.
Репликация через меседж брокер (Kafka) и самописные события в JSON формате, т.к. объемы данных на старте ожидаются небольшие и чтобы не потребовалась schema-registry.
Доменные события через меседж брокер (Kafka) и самописные события в JSON формате, т.к. объемы данных на старте ожидаются небольшие и чтобы не потребовалась schema-registry.
Один физический инстанс PostgreSQL (для снижения ops нагрузки на старте) с разными БД внутри под каждый BE. Если кому-то покажется хорошей идеей хранить данные не в реляционной модели, а в документной (а-ля Mongo), то у PostgreSQL есть хорошая поддержка JSONB. Придерживаюсь подхода Choose Boring Technology на старте.
- Не очень понял, куда деть отмену задачи, в контекст “Размещение задачи” или контекст “Выполнение задачи”. В “размещение” хочется, потому что там эта команда ближе к клиенту (ведь он ее выполняет), в “выполнение” хочется, потому что так “выполнение” будет единственным местом, где задача будет заканчиваться (успех, провал, отмена), что выглядит как хорошее разделение ответственности.
- Может ли быть контекст без агрегата, как, например, контекст “метчинг воркеров”?
- Решил не реплицировать воркеров из “Наем воркеров” в “Размещение задачи”, чтобы не усложнять. Решил, что необходимые данные о воркере в “Размещение задачи” будут попадать при синхронном метчинге из “Метчинг воркеров”, куда эти данные реплицируются.
- Не совсем уверен, можно ли делать одновременно и стриминг и доменные события по одним и тем же данным в одно и то же место. Кажется, что повышается риск получить данные в неконсистентном состоянии, если событие обгонит стриминг или наоборот.
- Не совсем уверен, хорошо ли передавать данные между контекстами “по цепочке”, например у меня сделано так, что данные из “размещения” попадают в “выполнение” через “сборку”. Опять же, опасаюсь, что если еще дополнительно будем стримить напрямую из “размещения” в “выполнение”, то повышается риск получить неконсистентные данные.
- Не уверен, что делать с менеджментом. Если во всей системе менеджмент покрывает ответственности найма воркеров, управление контентом (справочник типов заказов, набор тестов и т.д.), управление балансом воркера (начисление ему денег “просто так”), контроль качества, а самих воркеров немного, то было бы круто дать воркерам один удобный и быстрый интерфейс, где они смогли бы все это делать. Т.е. больше звучит как аспектная функциональность (как и нотификации). Пока что принимаю решение так и сделать - один менеджмент FE, который общается с разными сервисами, представляющими контексты.
Домен бизнеса MCF - освободить котов (сейчас тестировщиков happy cat box) от рутинных задач, которые можно делегировать. Предоставить быстрый и удобный способ заказать услугу по выполнению задачи, выбрать наиболее подходящего специалиста и выполнить с помощью него услугу.
Обнаружил следующие поддомены:
- клиент и обеспечение услуги
- подбор воркера к услуге
- снабжение услуги
- выплата зарплат
- наем воркеров
- контроль качества
- ставки для менеджеров
Обнаружил три Core поддомена:
- “клиент и обеспечение услуги”
- “подбор воркера к услуге”
- “наем воркеров”.
У всех них высокий показатель business diff, т.к. это ключевые проблемы, которые решает наш бизнес - нанять подходящих воркеров, принять услугу от клиента и найти для услуги лучшего воркера. У всех них не низкий model compl, т.к. характеристики воркеров и клиентов это весьма специфичные показатели. Поэтому эти три поддомена попадают в Core.
Максимальная business diff и model compl, т.к. содержит “уникальную систему метчинга [US-060]”.
Model compl выше, чем у “клиент и обеспечение услуги”, потому что проблема поддомена весьма сложная - подобрать воркера, который “входит в 3% лучших котов мира. [US-080]”. business diff тоже выше, чем у “клиент и обеспечение услуги”, т.к. на старте фокус бизнеса будет смещен к поиску и корректной оценке самых (топ 3%) элитных воркеров (это предположение необходимо верифицировать с бизнесом).
Минимальная model compl и business diff среди Core поддоменов. Коты-тестировщики happy cat box очень уставшие и вначале им требуется хоть какое-нибудь решение их проблем, главное чтобы качественно и в срок. Поэтому качество процессов, связанных с клиентом (регистрация, создание услуги, выполнение услуги с точки зрения информационной систем и т.д.) не так приоритетно, как подбор лучшего воркера к требуемой услуге. К тому же, характеристики клиента и его услуги куда более просты по сравнению с характеристиками воркеров (эти предположения необходимо верифицировать с бизнесом).
В какой-то момент возникла мысль поместить “клиент и обеспечение услуги” в supporting, т.к. в нем не было видно “уникальности” для бизнеса - поддомен выглядел достаточно простым, т.к. необходимо всего лишь принять запрос на услугу от клиента. Однако позже пришла мысль, что успешность подбора воркеров зависит еще и от характеристик услуги, которую запрашивает клиент, поэтому оставил этот домен в Core.
Обнаружил 4 Supporting поддомена:
-
“снабжение услуги”
-
“выплата зарплат”
-
“контроль качества”
Business differentiation у всех доменов приблизительно одинаковый, т.к. это важные поддомены для решения главной проблемы бизнеса, однако не уникальные, как в Core.
Самый сложный (высокий model compl) и один из самых уникальных (высокий business diff) среди всех supporting поддоменов, т.к. формирует процесс выполнения услуги и влияет на качество выполнения услуги и удовлетворенность клиента.
Средне-сложные и самые неуникальные supporting поддомены. “Выплата зарплат” чуть сложнее, потому что там больше условий. В выплате или получении денег ничего уникального кроме правил расчета для бизнеса нет.
Самый несложный, но один из самых “уникальных” supporting поддоменов. Контроль качества это внутренний процесс, в котором достаточно следить за жизненным циклом услуги и данных, которые к ней относятся. “Уникальность” и важность для бизнеса у него высока, т.к. именно через контроль качества происходит оценка успешности метчинга, что является важным для бизнеса на старте (это предположение необходимо верифицировать с бизнесом).
Обнаружил 1 generic поддомен - “ставки для менеджеров”
Его уникальность и важность (business diff) для бизнеса видится крайне низкой, т.к. это внутренний процесс, направленный на повышение эффективности менеджеров, которых в компании немного. Его “сложность” (model compl) так же видится низкой, т.к. это хорошо известный механизм ставок.
Выделил следующие bounded-контексты
- поддомен “клиент и обеспечение услуги”
- прием и выполнение услуг
- расчет и оплата услуг клиентом
- поддомен “наем воркеров”
- моделирование и подготовка тестов для вакансий и конкретных кандидатов
- прием заявок и тестирование кандидатов
- поддомен “подбор воркера к услуге”
- подбор воркера к услуге
- поддомен “снабжение услуги”
- сборка заказа
- интеграция с fur-tune поставщиком
- поддомен “выплата зарплат”
- расчет и выплата зарплаты
- поддомен “контроль качества”
- купили готовую систему контроля качества
- поддомен “ставки для менеджеров”
- система ставок для менеджеров
🤔 Пока сравнивал с ES, пришел к выводу, что “identity management” и “рассылка нотификаций” очень похожи на самостоятельные контексты, но не знаю, к какому поддомену их отнести и правильно ли выделять их в отдельные поддомены/контексты. С одной стороны, кажется, что да, т.к. их оценка и размещение на core domain chart и оценка характеристик имеют значение, с другой стороны - Ибрагим их не выделил. Решил выделить identity management в отдельный домен, т.к. вижу там целый кластер проблем: идентификация пользователей ( всех: воркеров, клиентов, менеджеров), хранение персональных данных, управление правами и т.д. Нотификации на отдельный домен не тянут, а вот на отдельный контекст - вполне, но пока их добавлять не буду.
- Полностью убрал контекст нотификаций.
- Аккаунтинг и биллинг разбился на два новых контекста.
- Выделился контекст интеграции с fur-tune поставщиком.
- Смержился контекст размещение заказа и выполнение заказа.
- в выплате зарплат воркерам и списании средств у клиентов были лишние шаги “генерирования инвойса”, убрал их. Теперь завершился цикл → снимаем / выплачиваем деньги.
- при приеме заказа от клиента вижу, что шаги “назначить воркера на заказ” и “рассчитать стоимость заказа” выглядят слишком низкоуровневыми, чтобы быть на ES диаграмме. Однако “рассчитать стоимость заказа” хочу оставить для отображения связи с контекстом “подбор воркера к услуге”, а “рассчитать стоимость заказа” хочу оставить для явно связи с контекстом “расчет и оплата услуг клиентом”.
Изменения в контекстах полностью соответствуют изменениям в ES модели.
Из плюсов отметил, что в общих чертах DM модель стала проще, стало меньше связей между контекстами. Из минусов - домен “прием и выполнение услуги” выглядит “монструозным” из-за связей с другими контекстами.
| Характеристика | Важность для проекта |
|---|---|
| Availability | Не так важно |
| Scalability | Не так важно (в общем) Очень важно (в конкретном поддомене) Ожидается низкая базовая нагрузка, информации о пиках нагрузки нет. Предполагаю, что раз это дочерняя компания (и множество клиентов ограничено), то скачков нагрузки не будет. НО эта характеристика важна у конкретного контекста “наем воркеров”, т.к. будет паблик и ожидается ddos. [US-081] Мы ожидаем 1 к заявок в день от рандомных котов, также, судя по отзывам, наши конкуренты могут попытаться нас заддосить в этом месте. |
| Modifiability | Очень важно Метрика влияет напрямую на TTM. ”Бизнесу необходим высокий низкий ТТМ (Time To Market), чтобы конкурировать на рынке.” |
| Maintainability | Не так важно |
| Securability | Средне важно Система работает с персональными данными (ФИО, адреса, контактные данные) + содержит детали о услугах (может быть чувствительная информация) |
| Performance | Не так важно “Общая нагрузка на систему не будет превышать 10 заказов в день и 100 клиентов. Воркеров будет 20 человек.” |
| Agility | Очень важно В некоторых частях системы у бизнеса есть опасения, поэтому необходимо быстро подстроиться к изменениям, если возникнут. Например: ”[US-170] Хоть получение каждого печенья поштучно под клиента выглядит странно, мы всё равно решили воспользоваться этой компанией.” ”[US-290] Это не самый критически важный проект для компании, поэтому он вряд ли будет часто меняться.” |
| Testability | Очень важно Как и Modifiability |
| Deployability | Очень важно Как и Modifiability |
| Usability | Не так важно Большая часть пользователей системы - клиенты, которые являются сотрудниками родительской компании, поэтому у них ожидается высокая лояльность и терпимость к системе. |
| Consistency | Не так важно В системе нет критичных процессов, которые бы требовали очень высокую consistency |
| Simplicity | Не так важно Как и Usability |
Выбираем из следующих стилей:
- layered
- modular monolith
- service-based
- microservices
Сравнение архитектурных стилей по характеристикам указывает на то, что лучше всего подходит микросервисный подход.
С микросервисным подходом в данном случае я согласен и хотел бы выбрать его, но это не означает, что нужно сделать микросервис per баундед-контекст. Т.к. бизнес находится в фазе роста, необходимо найди баланс, чтобы слишком не перегрузить систему и людей проблемами микросервисного подхода: коммуникации между сервисами, observability, debugging и т.д.
Выделил 5 сервисов:
по сервису на зарплату и оплату услуг - Отделил друг от друга, чтобы были независимые и были готовы к расхождению в логике обработки бизнес-событий.
сервис для приема заявок - отдельно, т.к. нужно уметь скейлить и выдерживать ddos.
сервис для подготовки заказа и интеграции с fur-tune поставщиком - объединил на первое время, чтобы не перегружать систему. Если начнет разрастаться - можно разделить, главное снимать метрики и следить.
“главный” сервис с полным жизненным циклом задачи, алгоритмом подбора воркера на задачу и системой ставок - объединил на первое время, чтобы перегружать систему. Если начнет разрастаться - можно разделить, главное снимать метрики и следить.
Разработчики алгоритма подбора обещали, что справятся с разработкой алгоритма на любом языке [US-070].
Система ставок не будет часто меняться [US-290] и сложной логики там нет.
Коммуникации:
- старался выбирать синхронные, чтобы было меньше технологического оверхеда. Как только синхронных коммуникаций перестанет хватать (напр. в логике метчинга воркера или в передаче заказа на сборку), то можно подумать о асинхронных.
- из “найма воркеров” в “подбор воркеров для задачи” выбрал стриминг, чтобы не блокировать процессы в найме добавление нового воркера в алгоритм.
- в сервисы с зарплатой и оплатой услуг выбрал асинхронную коммуникацию с помощью доменных событий, т.к. для расчета зарплаты/оплаты услуг важны доменные события, а не только конечные данные.
попробуйте расписать стейкхолдеров по группам из урока. Попутно пофантазируете, кого потенциально мы забыли указать в списке стейкхолдеров;
От себя добавил таких стейкхолдеров:
- кандидаты в воркеры
- воркеры
- сборщики заказов
- датасайнтисты / разработчики алгоритма метчинга
выберите один из семи архитектурных стилей, описанных в уроке. Опишите, почему вы сделали такой выбор и по каким критериям сравнивали стили (можно использовать картинку из урока со сравнением стилей);
- если выбрали распределённый архитектурный стиль, опишите, какие сервисы будут отдельно, и объясните, почему каждый из сервисов должен быть отдельно от остальных;
“Инфраструктуру считаем бесплатной, прямо как в уроке, так как Happy Cat Box расскажет нам, как такое организовать” - получили от бизнеса (дано в уроке)
Вывод: цену инфраструктуры не учитываем.
“Соблюдение CatFinComplience, который говорит об особом способе хранения данных и особой наблюдаемости за системой. Компания не хочет повторять опыт с маски-шоу, которые были в Happy Cat Box.” - получили от бизнеса (дано в уроке) Нужно обратить внимание на условия и решение, примененное в Happy Cat Box:
регуляторы требуют от бухгалтеров хранить финансовую информацию на территории страны и без возможности её изменить после проведения;
scalabilityavailability для контекста “прием заявок и тестирование кандидатов” (из US-081 DDoS)- agility, testability и deployability - из-за низкого TTM, для всей системы
- agility для поддомена “подбор воркера к услуге”
- modifiability и maintainability - из high model complexity поддоменов “клиент и управление услугами”, “подбор воркера к услуге” и “расширение штата воркеров”
- высокая scalability, maintainability, modifiability, testability, agility и evolvability - для всей системы, т.к. система находится на стадии роста + от стейхолдеров известно, что будет в 10 раз больше заказов.
- высокая securability и consistency - для контекстов “выплат”, для соблюдения CatFinCompliance. (от юристов)
- высокая modularity и evolvability - для поддоменов “подбор воркера к услуге” и “расширение штата воркеров”, требование от топ-менеджмента
- базовый релизный цикл (для всей системы) - месяц
- релизный цикл для поддомена “подбор воркера к услуге” - максимум неделя
- agility, modularity и testability - для контекста “расчет и оплата услуг клиентом”, т.к. будут добавляться новые способы оплаты.
- изолированный поддомен “повышения мотивации менеджеров”
- observability - для всей системы, требование от администратором
- availability - от клиентов, для контекста “прием и выполнение услуги”
- simplicity - от разработчиков (посмотрим, нужно ли как-то явно выполнять или нет)
Берем наши контексты и принимаем решения:
- "поставка fur-tune печений клиенту” - внешняя система, поэтому отдельно
- “готовая CRM для контроля качества и связи с клиентами / воркерами” - внешняя система, поэтому отдельно
- “система ставок для менеджеров” - отдельная подсистема, т.к. по требованиям стейкхолдеров необходимо его “спрятать” от всех остальных частей системы, разрабатывать, деплоить, мониторить отдельно.
- “прием заявок и тестирование кандидатов” - отдельная подсистема, т.к. ему необходимо обеспечить высокую availability (user-facing + ddos)
- “система метчинга воркера на услугу” - отдельная подсистема, т.к. ему необходимо обеспечить ускоренный релизный цикл.
- “расчет и выплата зарплаты” - отдельная подсистема, чтобы выполнять требования каплаенса, безопасности и legal по хранению и обработке данных.
- “расчет и оплата услуг клиентом” - отдельная подсистема, т.к. будет расширяться методами оплаты (тут не уверен, стоит ли выносить в отдельный, возможно, это лишнее и можно по-началу смержить с “зарплатным” сервисом, т.к. характеристики не конфликтуют)
- “прием и выполнение услуг” и “подготовка расходинков для услуги” - мержу в одну подсистему, т.к. характеристики не конфликтуют, не хочется делать лишнюю подсистему, чтобы снизить операционную нагрузку на систему.
Итого, после предыдущего шага получилось 6 подсистем, т.е.:
- 5 одноименных подсистем, содержащих один контекст
- 1 подсистема “исполнения услуг”, который содержит контекст “прием и выполнение услуги” и “подготовка расходников для услуги”
Подсистема “исполнения услуг” - modular monolith, потому что содержит два контекста, которые мы хотим доменно отделить друг от друга (для большего порядка внутри подсистемы, для параллелизации работы над подсистемой, для готовности разделить в разные сервисы если понадобится)
Подсистема “метчинга воркера на услугу” - pipeline, чтобы обеспечить высокую flexibility, modularity и modifiability, которую хочет как бизнес, так и разработчики.
Подсистема “ставки для менеджеров” - layerd monolith, выбираем самый простой и привычных стиль, т.к. не содержит сложной логики и критической для бизнеса функциональности.
Подсистема “прием заявок и тестирование кандидатов” - microkernel, т.к. должна иметь высокую modifiability, modularity, evolvability для быстрого реагирования на изменения бизнеса (например, в случаях, когда результаты проверки гипотез приведут к новым фичам для этого контекста).
Подсистемы “расчет и оплата услуг клиентом” и “расчет и выплата зарплаты” - layered monolith, несмотря на то, что бизнес-логика сложна, выбираем простой и привычный стиль, чтобы не усложнять эти подсистемы (simplicity).
Документоориентированная база данных будет использоваться в двух подсистах
- прием заявок и тестирование кандидатов
- система метчинга воркера на услугу
Будет один физический инстанс с логическим разделением на две разные базы данных для снижения операционных расходов в системе.
В этих подсистемах не критичная консистентность, однако критичная flexibility и modifiability данных (для частых изменений в подсистемах)
Реляционная база данных будет использоваться в остальных подсистемах.
Для подсистем “выплат зарплат” и “оплаты услуг” географические расположение данных и соблюдение комплаенса, это будет отдельный инстанс базы данных.
Для подсистемы “исполнения услуги” выбираем тот же типа базы данных для технологической консистентности и упрощения одной из самых крупных подсистем.
Для подсистемы “ставок” выбираем тот же типа базы данных по тем же причинам + это будет отдельный инстанс, чтобы “спрятать” его от остальных в компании (требование стейкхолдеров)
В местах, где задержка в актуализации данных не так критична, однако данные нужно поддерживать в актуальном состоянии выбирал асинхронную коммуникацию через репликационные события (напр. стриминг из “исполнения услуг” в “выплаты зарплаты” и “оплату услуг”)
В местах, где не так много логики и достаточно on demand получить небольшое количество данных, выбирал синхронную коммуникацию. (напр. расчет скидки, получение воркера к услуге, запрос печенья при сборке)
В местах, где бизнес-логика зависит от событий и в то же время нет необходимости немедленного получения результата выбирал асинхронную коммуникацию с помощью отправки бизнес-событий, чтобы не блокировать процесс-emitter событий. (напр. получение доменных событий в сервисах “выплаты зарплат” и “оплаты услуг”, в сервисах “ставок” и “контроля качества”)
При выборе между асинхронной доменной коммуникацией и синхронной преимущество имела синхронная для простоты системы и низкого порога вхождения имплементаторов.
- покрытие тестами
- core-поддомены 90%
- остальные поддомены 60%
- проверка соблюдения необходимой периодичности релизов
- “система метчинга воркера на услугу” - максимум 1 неделья
- остальные подсистемы - максимум 4 недели
- репорты о выданных доступах в БД
- критично для подсистем “выплата зарплат” и “оплата услуг”
- ручной контроль соблюдения архитектурных стилей
- модульный монолит для подсистемы “прием и выполнение услуги”
- микрокернел для подсистемы “приема заявок и тестирования кандидатов”
- пайплайн для подсистемы “метчинга воркера на услугу”
- в будущем возможна имплементация с помощью ArchUnit, т.к. система будет написана на Java стеке (язык Kotlin), но на старте проекта на это не стоит тратить время
- ручной контроль доступов к подсистеме “ставок” (код, документация, окружение и т.д.)
- ручное отслеживание достаточно высокого уровня observability всей системы
- сбор необходимой базовой телеметрии со всех компонент
- автоматический контроль availability с помощью мониторинга значения и алертинга в случае нарушений
- у подсистемы “прием заявок и тестирование кандидатов” - на старте достаточно 99%
- у подсистемы “прием и выполнение услуги” - 99.9%
- автоматический контроль scalability с помощью нагрузочных тестов в пайплайне
- у подсистемы “прием заявок и тестирование кандидатов” - на старте достаточно 99%
- у подсистемы “прием и выполнение услуги” - 99.9%
- автоматический контроль reliability у поддомена “прием заявок и тестирование кандидатов” с помощью эмуляции ddos атаки на live окружении
- анализ метрик coupling и cohesion вручную методом исследования кода и автогенерируемой документации
- подсистема “прием заявок и тестирование кандидатов”
- подсистема “система метчинга воркера на услугу”
- подсистема “прием и выполнение услуги”
Accepted
Необходимо принять решение, в каком виде будет реализован контекст “прием заявок и тестирование кандидатов” в системе:
- будет самостоятельным сервисом
- будет объединен в один сервис с другим контекстом, имеющим схожие характеристики - “прием и выполнение услуги”
Решено иметь контекст “прием заявок и тестирование кандидатов” изолированно в отдельном сервисе, так как:
- помимо высокой availability у сервиса есть риск быть подвергнутым DDoS атакам, потому что сервис доступен в интернете.
Для обеспечения высокого значения resilience (отказоустойчивости) всей системы и чтобы не перемешивать контексты из разных поддоменов решено не объединять с контекстом “прием и выполнение услуги”, а сделать самостоятельным сервисом.
В результате этого решение вырастает нагрузка на поддержку и обеспечение всей системы, однако это намного меньшее зло, чем подвергнуть риску выводу из строя сразу обе подсистемы / контекста.
К сожалению, может быть проверено только вручную архитектурным ревью системы.
- контекст будет объединен в один сервис с другим контекстом, имеющим схожие характеристики - “прием и выполнение услуги”
- зарисовал “нулевую” систему в привычной нотации (сервисы + коммуникации)
Система из нулевой домашки
Система из нулевой домашки в привычной нотации

- добавил неочевидные коммуникации в “нулевую систему”
- убрал аспектные / инфрастуктурные сервисы, не учитываем их при анализе
- считаю инстабилити и нахожу отмечаю самые проблемные места
- нахожу, где в моей AS IS находятся контексты TO BE
| TO BE контекст | Поддомен | где находится в AS IS | Статус |
|---|---|---|---|
| прием и выполнение услуги | generic | order placement и order execution | не совпало |
| подготовка расходников для услуги | supporting | order execution | не совпало |
| система метчинга воркера на услугу | core | worker matching | совпало |
| прием заявок и тестирование кандидатов | core | worker onboarding | совпало |
| расчет и оплата услуг клиентом | generic | accounting and billing | не совпало |
| расчет и выплата зарплаты | generic | accounting and billing | не совпало |
| система ставок для менеджеров | supporting | нет | не совпало |
Анализирую сравнение, получается список того, что необходимо поменять / добавить:
- “order placement” и “order execution” нужно смержить в один сервис (в котором находятся два контекста “прием и выполнение услуги” и “подготовка расходников для услуги”) - надо менять
- “система метчинга воркера на услугу” матчится 1 к 1 с “worker matching” - не надо менять
- “прием заявок и тестирование кандидатов” матчится 1 к 1 с “worker onboarding” - не надо менять
- “accounting and billing” должен распасться на 2 сервиса: “расчет и оплата услуг клиентом” и “расчет и выплата зарплаты” - надо менять
- “система ставок для менеджеров” отсутствует - надо добавить
Мы находимся в условиях отсутствия опыта (в моих кругах это более частый случай), поэтому тактика будет такой:
- мигрируем систему от простых элементов к сложным
если приоритеты позволяют, начинаем с отсутствующих элементовв нашем случае распределенная инфрастуктура уже есть и используется в проде, поэтому не актуальноначать с generic, закончить coreв нашем случае core поддомены совпали, поэтому core мигрировать не требуется- начать с меньших элементов, закончить большими
Составляю список изменений:
- добавление нового сервиса “система ставок для менеджеров”
- добавление нового сервиса с двумя контекстами “прием и выполнение услуги” и “подготовка расходников для услуги” вместо двух существующих сервисов “order placement” и “order execution”
- добавление двух новых сервисов для денег вместо текущего одного “accounting and billing”
Предположим, что приоритеты нам позволяют начать наш проект перехода с добавления нового сервиса.
Имплементируем сервис, подключаем его к нашей инфраструктуре доменных событий по Task и Client сущностям.
Этим слегка повышаем instability “order execution service” сервиса с 0.5 на 0.6, но считаем это допустимым, т.к. это временные эффект.
- добавляем логику сервиса “order placement service” в сервис “order execution service”, а после убираем “order placement service”. получаем вместо двух сервисов с 0.6 и 0.6 instability один на 0.83 instability. Делаем это через CDC.
- делаем рефакторинг внутри сервиса на модульный монолит, извлекаем логику подготовки расходников в отдельный модель и получаем два контекста: “прием и выполнение услуги” (0.83 instability) и “подготовка расходников для услуги” (0 instability)
Step 4.3 adding two new service for money-related processes instead of a single "accounting and billing"
- отказываемся от стриминга воркеров из “worker onboarding service” в “accounting and billing service”, т.к. эта избытычно. воркеры в биллинг должны попадать только из одного места и в таргет решении это будет “прием и выполнение услуги”. “Вспоминаем” про то, что нам нужно считать скидку (про эту фичу просто забыли), добавляем это как синхронную связь (как в таргет решении). Меняем instability с 0 на 0.25.
- Распиливаем монолитный биллинг на два сервиса, в каждом по контексту “расчет и оплата услуг клиентом” и “расчет и выплата зарплаты” с помощью CDC.
- После окончании имплементации двух новых сервисов включаем в систему новые, отключаем старые. Оставляем старый сервис функционировать, чтобы вернуться на него в случае роллбека. Верифицируем корректность работы новых сервисов с помощью сравнения данных из старого.























