Для имитации request/reply используем две разных очереди сообщений. Сообщения можно связывать по CorrelationId (Id моего сообщения превращается в CorrelationId ответа) или через временные очереди (очереди только для одного сообщения, вероятно, будет огромный overhead на создание/удаление очередей).
Kafka оптимизирована под постоянный поток простых сообщений key/value, с нагрузкой до 1M/s и только под паттерн Publisher/Subscriber. RabbitMQ удобнее для транзакционных сообщений (в том числе большого размера), нагрузка до 10K/s с поддержкой трех разных паттернов (point-2-point, publisher-subscriber и exchange/routing - распределение сообщения по разным очередям)
Для архитектора важна не только глубина знаний ("знаю, что знаю"), но и ширина знаний ("знаю, что знаю + знаю, что не знаю"). Чтобы повышать ширину знаний, нужно больше читать о новых событиях в мире, например, InfoQueue, Technical Radar или DZone.
Микросервисы отличаются сложностью отладки, поэтому нужны хорошие логи. Выбрать инструмент для сбора логов (splunk, logstash, kafka и другие) - половина дела. Полезные приёмы:
- "консолидация логов" - объединение логов от разных микросервисов в один лог
- "идентификатор контекста запроса"
- "иерархия идентификаторов" (если есть userId - используем его, если нет, то requestId, если нет, то applicationId и т.д.), отличное место для извлечения id context - api gateway
- консистентность контекста - принимать его как входной параметр по всех запросах
- собственный wrapper для логов - это хорошо
При разделении монолита на микросервисы, по возможности, изменение архитектуры стоит вести параллельно с разворачиванием инфраструктуры и CI/CD процессов (силами devops)
- монолитные архитектуры (microkernel, layered, pipeline, modular monolith)
- распределенные архитектуры (microservices, space-based, event-driven, service-based): создание контракта, поддержка, версионирование и координация контракта; проблемы с доступностью сервисов, медленнее вызовы удаленных процедур и протоколов, чем локальные; аутентификация и авторизация удаленных вызовов; распределенное логирование; атомарные транзакции и область видимости транзакции
Процесс анализа архитектуры - это изучение текущего состояния архитектуры проекта и подготовка советов, которые позволят его улучшить. Структурный распад - нарушение архитектурных принципов, которые были использованы при разработке архитектуры проекта
Во время анализа архитектуры важно разделить систему на компоненты. Компонентами могут быть подсистемы, слои, сервисы, обработчики событий, то из чего состоит приложение. В микросервисной архитектуры, как правило, компонентом является сам микросервис. Архитектура рассматривает взаимодействие между компонентами, а не их внутреннее устройство.
Индикаторы структурного распада на макро-уровне (всей системы):
- статичное связывание (static coupling)
- временное связывание (temporal coupling)
- размер компонентов (component size)
Индикаторы структурного распада на уровне микросервисов:
- большое количество межсервисных взаимодействий
- большое количество оркестрирующих запросов (один входящий и много исходящих)
- большое количество агрегирующих запросов (для ответа на входящий запрос, нужно сагрегировать информацию с многих других сервисов)
- связывание баз данных (разделение баз данных между разными микросервисами)
Значение метрик не столь важно, сколько тенденция их изменения. Важнейшие метрики по Ричардсону:
- количество классов в сборке (в среднем)
- количество строк кода
- средняя сложность (1 + количество путей, чтобы пройти метод, целевое значение 2-4)
- глубина дерева наследования
- цикломатическая сложность (V = e - n + 2, e - edges - количество переходов между операторами, n - nodes - количество операторов)
- количество афферентных связей (центростремительных, внутренних)
- количестве эфферентных связей (выносящих, внешних)
Command Query Responsibility Segregation - паттер проектирования, который предполагает разделение команд, меняющих состояние в базе данных, и запросов, которые получают данные из базы. Операции базы данных на чтение и запись требуют разных оптимизаций, поэтому разделение базы на две части - "базы на чтение" и "базы на запись" (первая база синхронизируется со второй) даст выигрыш в скорости. Дальнейшая оптимизация: разделение исходного сервиса на два: микросервис на чтение будет работать с высокопроизводительным кешем в оперативной памяти (memcache, redis), микросервис на запись - обновлять данные в базе данных ("холодное хранилище") и горячем кеше читающего сервиса.
Схемы для организации сводных отчетов:
- database pull model - сервиса отчетов забирает данные из БД продуктовых сервисов (нарушение bounded context)
- http pull model - сервис отчетов забирает данные из API продуктовых сервисов (проблемы с производительностью, объемом данных)
- event-based push model - публикация событий на стороне продуктовых сервисов, обработка и агрегация событий в БД сервиса отчетов
Миграция - замена некоторого компонента с заданным функционалом на новый. При миграции легко откатить изменения, снижается общий риск, но требует переключения логики запросов при смене компонентов. Адаптация - расширение функциональности уже имеющегося компонента ("на месте", без разворачивания нового сервиса). Адаптация сложнее в откате изменений, вызываемые компоненты не меняются. Выбор между миграцией и адаптацией определяется риском, стоимостью и связаностью системы.
При объяснении бизнесу "Зачем нам нужен рефакторинг?" не стоит использовать технические термины как всё станет здорово, следует четко объяснить, почему бизнесу нужно за это заплатить. Основных мотивации для бизнеса три: снижение расходов, снижение time-to-market, удовлетворенность пользователей.
Пустые обещания ничего не стоят, обязательно нужно показывать измеримые метрики. Снижение расходов - количество багов, время на разработку и тетисрование; время поставки - часы разработки и время от идеи до поставки в продуктовую среду; удовлетворенность пользователей - количество багов, количество баг-репортов от пользователей, метрики производительности и скорости. Не стоит использовать опросы пользователей, они очень субъективны и предвзяты.
В командах архитекторов не может быть общего мнения, конфликты являются нормой. Целью работы команды архитекторов является выработка общего мнения, основанного на знаниях всей команды. В качестве решения можно использовать выбор медиатора; который после тщательного обсуждения мотивированных предложений, сделает решение. Тогда, все оставшиеся члены команды должны согласится с принятым решением.
Архитектурные компромиссы: производительность, масштабируемость, расширяемость, гибкость, ремонтопригодность (maintainability) и осуществимость (feasability) - по бюджету и срокам. ATAM (Architectury Tradeoffs Analysis Method) - способ анализа предлагаемых архитектур на соответствие бизнес-задачам и атрибутам качества. Минусы процесса: предлагаемая архитектура должна быть готова, stakeholders очень заняты и часто распределены, предполагает однократный процесс, без эволюции, предполагает, что все бизнес-требования известны.
Этапы процессе:
- создать презентацию архитектуры
- валидация архитектуры и определение компромиссов
- идентификация и разрешение рисков
- утвереждение у stakeholders.
CBAM (cost-benefit analysis method) основан на максимизации разницы между преимуществами и стоимостью. ATAM Technical Report
Заблуждения, касающиеся распределенных систем:
- сеть надежна
- задержка равна нулю (это не локальный вызов в памяти!)
- пропускная возможность каналов бесконечна
- сеть безопасна
- топология сети не меняется
- есть только один администратор
- транспортные затраты равны нулю (завтраты на сетевое оборудование)
- сети гомогенные
В книге "Enterprise Integration Patterns" (Hohpe, Wolf, 2003) определяется четыре стиля интеграции: передача файлов, общая база данных, удаленный вызов процедур и сообщения. Основные протоколы передачи для файлов - FTP/SFTP, HDFS (Hadoop), SCP (Secure Copy Protocol), SMB (Server Message Block), CIFS (Common Internet File System). Преимущества: универсальный, простая интеграция, полная абстракция систем. Минусы: обработка ошибок очень сложна, медленная синхронизация данных (как узнать, что данные уже пора читать? только по расписанию?), передача исключительно только данных.
Приложения ничего не знают друг о друге, но используют одну базу данных. Преимущества: универсальная интеграция (почти все системы доступны через SQL/ODBC), абстрация систем, независимость систем ("decoupling"), простота интеграции. Недостатки: плохо работает с ORM (ORM построены по принципу эксклюзивного владельца БД; много промахов кеша на стороне ORM), сложности с "бутылочными горлышками" производительности, сложности с изменениями схемы; данными не владеет никто.
Приложение удалённо вызывает процедуру другого приложения и получает ответ. Используемые протоколы: REST (Representational State Transfer), SOAP (Simple Object Access Protocol), RMI (Remote Method Invocation), CORBA (Common Object Request Broker Architecture), WebSockets, gRPC. Преимущества: инкапсуляция данных и четкий владелец данных, внешняя интеграция систем (интеграция за файрволлами, шлюзами), экосистема фреймворков и инструментов. Недостатки: жесткая связность приложений, не реализуется асинхронная коммуникация, не реализуется "broadcast" (вещание ответа на запрос для многих потребителей).
Подход с использованием "шины сообщений", "брокера сообщений". Протоколы: JMS (Java Messaging Service), MSMQ (Microsoft Message Queue), AMQP (Advanced Messaging Queuing Protocol), SNS (Amazon Simple Notification Service), SQS (Amazon Simple Queue Service), STOMP (Simple Text Oriented Messaing Protocol), SMPP (Short Message Peer-to-Peer), MQTT (MQ Telemetry Transport). Преимущества: отсутствие связности систем, гарантированная доставка, асинхронная коммуникация, "вещание на широкую публику", легко масштабировать. Недостатки: сложная интеграция за файрволлом, сложность реализации, сложность тестирования, кросс-платформенные стандарты, асинхронная обработка ошибок.
Оркестрация - подход в котором есть "дирижер", центральный управляющий сервис. При хореографии центрального дирижера нет, поэтому или задача для сервиса должна включать в себя весь нужный контекст, или же сервис должен обладать информации, где и как получить недостающую информацию.
Традиционные корпоративные модели: модель бизнес-процессов (business workflow) - иллюстрирует и описывание бизнес-процессы, модель корпоративных систем (enterprise systems) - системы и их взаимодействие, корпоративная информационная модель (enterprise information) - физические и логичные модели данных и их обмен, технологическая инфраструктурная модель (technology infrastructure) - описание расположение серверов и виртуальных машин, бизнес-автоматизации (business automation).
Концепция "бережливого моделирования":
- создать некоторые списки;
- отслеживать взаимодействие между элементами списков;
- хранить элементы в определенном порядке в хранилищах/репозиториях.
Примеры списков: список владельцев ответственности, основные бизнес-функции, приложения и сервисы/микросервисы, технологии и платформы, группы пользователей и роли, стандарты, хранилища данных, бизнес-подразделения.
Пример отношений: какие базы данных и приложения поддерживают определенную бизнес-функцию? Связывает списки хранилища данных, приложений и сервисов и основных бизнес-функций.
Архитектурная абстракция - та информация, которую мы можем скрыть о компоненте, без вреда для понимания системы в целом.
Пять уровне абстракции:
- location transparency, например "172.56.33.98" - явное указание адреса
- name transparency, например "PricingService" - явное указание имени
- implementaiton transparency, например "Java" - явное указание языка/платформы реализации
- access decoupling, что мне нужно знать о протоколе, чтобы использовать его? Например, AMQP
- contract decoupling, например: { ProductId, Quantity}.
Метод взаимодействия | Location t. | Name t. | Implementation t. | Access decoupling | Contract |
---|---|---|---|---|---|
Сообщения (messaging) | OK | OK | OK | No | No |
Адаптер (отдельное приложение между целевыми) | OK | OK | OK | OK | OK |
REST | ? (OK with proxy) | OK | OK | No | No |
Message bus (ESB) | OK | OK | OK | OK | OK |
Review boards ("доска ревью") в больших компаниях применяется для определения стандартов, одобрения решений, одобрение отхода от стандартов, создание рекомендаций и руководств. Это мощный и полезный инструмент, но он может быть "бутылочным горлышком".
Методы устранения "бутылочного горлышка":
- Используй короткие и частые встречи, а не редкие и длинные (лучше раз/два в неделю, чем раз в месяц или квартал)
- Делай публичную повестку встречи (например, в wiki) для быстрого доступа
- Разделяй каждую тему на "к обсуждению" или "к принятию решения" до собрания
- Проверь, что правильные stakeholders и лица, принимающие решения присутствуют на встрече
- Установи жесткий лимит на время презентации, проверь, что все выступающие знают про этот лимит
Паттерн "Предохранитель" (Circuit Breaker): встает между сервисом и потребителем и при возникновении проблем у основного сервиса, "предохранитель" разрывает связь и моментально отвечает потребителям, что сервис недоступен (экономит им время на ожидании ответа от перегруженного сервиса). Одновременно, он защищает основной сервис, который испытывает проблемы, от огромной "продуктовой" нагрузки и дает ему время восстановиться.
"Предохранитель" использует простой heartbeat от сервиса, простые синтетические транзакции для проверки работоспособности (не продуктовые) и мониторинг работы реальных пользователей (real user monitoring).
"Direct access design" - API слой может вызывать любые endpoint внутренних модулей/классов. "API access design" - предполагается создание API-фасада, который ограждает вызов внутренних endpoint "снаружи". Плюсы доступа через API: разделение интересов (внутренние методы отвечают исключительно за бизнес-логику, не выставляют внаружу endpoints), protocol-agnostic (независимость от протокола: json, protobuf), создание каталога сервисов в фасаде.
Component Coupling (связность компонентов) означает степень, насколько компоненты знают о других. Afferent coupling (приносящая связаность) - связность элементов, которые зависят от целевого. Efferent coupling (исходящая связность) - связность компонента, от которых зависит наш целевой компонент (fan-out). Temporal coupling (временная связность) - означает, что компоненты связаны временной не-статичной зависимостью (например, некий компонент А зависит от B и C, и существует жесткий временной порядок из вызова, например, сначала B, а потом C).
Степени связности (от более сильной к менее):
- патологическая связность (один компонент полагается на внутренние детали реализации другого компонента)
- внешняя связность (множество компонентов делят внешне установленный протокол или формат данных), микросервисы всегда имеют внешнюю связность (один выставил REST - все обязаны использовать REST)
- связность контроля (один компонент передает информацию другому, что тот должен сделать (внешний decision maker))
- связность данных (компоненты используют один контекст данных (формат, источник))
Взаимодействия владельца продукта и архитектора на нулевой итерации: владелец продукта создает эпики и user-story, архитектор выявляет характеристики, определяет компоненты, выбирает шаблоны проектирования, составляет архитектурные диаграммы, документирует решения, оценивает архитектурные риски. На следующих итерациях архитектор так же анализирует архитектуру, определяет рефакторинг компонентов, гарантирует соблюдение принципов. Команда разработки каждую итерацию валидирует архитектуру/решения.
Приемы для эффективного представления архитектуры:
- "соединительные швы" (разделять слайды на "для менеджеров", "для разработчиков" и т.д.)
- "слайды-аккордионы" ("боковые ответвления" основной презентации с более подробной информацией, если есть время, чтобы её рассказать)
- анимация (для объяснения процесса лучше использовать анимацию, а не перегруженный слайд)
- размеры и фокус (делай прозрачным те части системы, про которые сейчас нет рассказа)
- "строительство" (построение схемы шаг за шагом, как она создается логически)
Приемы для хороших диаграмм:
- заголовки: короткие и осмысленные; используй номера, если важен порядок
- линии: предпочитай однонаправленные стрелки, подписывай стрелки для дополнительной информации
- форма блоков: не предлагай людям догадываться, что они означают, будь единообразным
- метки (название блоков): не используй аббревиатуры, особенно не все стейкхолдеры их понимают
- цвета: удостоверься, что означают что-то важное; проверь схему для дальтоников и на черно-белых принтерах
- ориентация: размещай самое важное в центре; будь единообразным в разных диаграммах
- легенда: объясняй формы, линии, цвета, границы и т.д.
Используй c4 model (system context, container, components, classes of code) и The Open Group ArchiMate.
Классификация микросервисов:
- функциональные сервисы - сервисы с публичным API, обрабатывающие запросы пользователей с бизнес-функциональностью
- сервис-оркестратор - сервисы с публичным API, оркестрирующие вызовы несколько сервисов на один запрос клиента
- инфраструктурные сервисы - приватные сервисы с инфраструктурными задачами (аудит, логирование и т.д.)
- агрегирующие сервисы - сервисы с публичным API, которые обрабатывают агрегирующие запросы бизнеса
- сервисы-шлюзы - сервисы с публичным API, которые обрабатывают вызовы сторонних сервисов со сменой контракта или протокола
Классификая сервисов полезна для аннотации сервисов (декораторов, определяющих доступ к API)
Выделение доменов сервисов необходимо для логической группировки большого (несколько десятков) количества микросервисов. В реальности выделение доменов может быть полезно в api layers слое.
Задача: Как при использовании внешнего сервиса конфигурации известить клиентов об изменении конфигурации?
Шаблон "Широковещательный сервис" (service broadcast): сервис конфигурации передает сообщение брокеру сообщений (напр.RabbitMQ), который с помощью broadcast-очереди отправляет его всем подписанным сервисам. Минусы: брокер - единая точка отказа.
Шаблон "Широковещательный домен" (domain broadcast): брокер сообщений поднимается для каждого домена (например, 3-4 брокера на систему). Минусы: сложнее поддерживать, точка отказа сохранилась.
Шаблон "Дозор" (Watch): клиенты знают о местонахождении сервиса конфигурации и опрашивают его самостоятельно; при изменении конфигурации, сервер конфигурации по листу зарегистрированных клиентов, рассылает уведомления о событии / измененный конфиг.
Встроенный (embedded) брокер - брокер сообщений, который являются частью единицы развертывания (например, виртуальной машины). Классы, работающие на одной машине, коммуницируют через очереди сообщений. Данный подход позволяет избавляться от "бутылочных горлышек" и использовать параллелизм внутри одной виртуальной машины.
Встроенный брокер можно использовать как часть внешнего API. Соединиться, положить в очередь внутреннего брокера, отключиться. Ответ принять аналогичным способом.
Интересы бизнеса | Атрибуты качества |
---|---|
time to market | agility (скорость изменений), testability (быстрая проверка), deployability (частые деплои без ожиданий) |
user satisfaction | performance, availability, fault tolerance, testability, deployability, agility (медленные, недоступные или ошибающие приложения бесят) |
готовность к слияниям и поглощениям | agility, scalability, learnability, interoperability (documentation + simplicity), adaptability |
competitive advantage | agility, testability, deployability, scalability, availability, fault tolerance, adaptability |
Мы не можем напрямую маппить требование качества в интерес бизнеса, например agility != time-to-market, потому что: agility + testability + deployability = time-to-market
- функциональный подход (function-driven)
- подход от данных (data-driven)
- подход запросов/API (request-driven, API-driven)
Порядок выделения микросервисов при проектировании:
- Определите крупные функциональные области (функциональный подход)
- Создайте крупные функциональные микросервисы (функциональный подход)
- Сопоставьте сервисы с хранилищами данных (подход данных)
- Переработай сервисы так, чтобы поддерживалась изоляция данных (подход данных, функциональный подход)
- Добавь зависимости между сервисами, сохраняя изоляцию данных (подход данных, функциональный подход), при необходимости повтори п.4
- Добавь слой оркестрации запросов (API): API-подход, при необходимости повтори п.4
39. Integration Hubs
Главная задача интеграционного хаба: разорвать связность каждой пары связанных сервисов. Если сервис связан с 10 другими и потребует изменение протокола, то придется внести изменения в 10 других сервисов. При применении интеграционного хаба, необходимо будет только вменить интеграцию хаба и сервиса.
Возможности интеграционного хаба:
- улучшение сообщение (message enhancement)
- трансформация сообщений
- трансформация протокола
- оркестрация сервисов
- обнаружение и поиск сервисов
- абстрагирование системы
- "развязывание" контракта
- consumer/producer: как мы будем получать и отправлять сообщения?
- wiretap ("прослушка"): как мы будем проверять сообщения, без их обработки?
- splitter: как мы будем разделять сообщения по множеству частей?
- transformation: как мы будем конвертировать сообщения из одного формата в другой?
- enhance: как мы будем модифицировать сообщения до их отправки?
Остальная часть ролика, про Apache Camel - фреймворк для интеграции.
Применение версионирования на уровне headers (например, Accept: application/vnd.service.trade.v2+json) без изменения route и endpoints. На стороне бекенда можно использовать регулярное выражение для разбора header Accept. Стоит помнить про стратегию вывода версии контракта (contract deprecation version strategy).
Данные - самый важный актив компании. При повреждении приложения - функциональность легко восстановить, при повреждении данных путей для восстановления может вовсе не быть. Миграции данных могут случаться при разделении монолита или при объединении двух микросервисах в один. При таком рефакторинге, применение резервных копий данных (бекапов) может быть невозможным. Мигрируйте по частям функционала, в первую очередь сервисы; миграция баз данных начинается после стабилизации архитектуры/микросервисов.
Паттер "Оркестрация" предполагает наличие "дирижеры" (conductor). API-шлюз (API Gateway) отлично подходит для безопасности, генерации id запроса, поиска микросервисов, аудита, метрик, но не является хорошим выбором для оркестратора (из-за проблем с мультикастингом, фиксацией контрактов, распортранение ломающих изменений контракта на уровень API-шлюза).
Ричардсон рекомендует для оркестратора создавать отдельный микросервис. Это позволяет создавать отдельный endpoint под выделенный специфичный запрос, которые требует оркестрации. Нет проблем с распределением контекста (API слой не страдает от изменения контракта).
Микросервис-агрегатор собирает в себя информацию с других микросервисов для быстрых ответов на запросы, требующие агрегации результата из разных микросервисов. Агрегатор может использовать брокер сообщений для получения информации из других микросервисов и может дублировать информацию, которая хранится в других микросервисах.
Шаблон "Контрольная сумма" (checksum) - микросервис по синхронному каналу сообщает количество/идентификатор последнего отправленного сообщения по асинхронному каналу (через брокер сообщений).
Шлюз служит для доступа к системам, отличных от типовых микросервисов (например, использующих протокол OTMA - протокол IBM IMS V13, что-то очень древнее и страшное для мейнфреймов IBM). Ричардс предлагает использовать отдельный шлюз (отдельное приложение) для каждой группы функциональности системы, которую он закрывает. Преимущества: при замещении функционала на новую реализацию, можно будет использовать шлюз как "anticorruption level", замещать шлюз на новую реализацию бесшовно.
"Реактивный" манифест: система должны быть отзывчивой, упругой, эластичной и управляться сообщениями (message driven). Система отвечает последовательно, быстро и своевременно, когда это возможно. Система сохраняет отзывчивость после сбоев с помощью репликации, сдерживания (containment), изоляции и делегирования. Система остается отзывчивой под разной (варьирующейся) нагрузкой. Система полагается на асинхронные сообщения для снижения связанности, изоляции, прозрачности локации (location transparency) и делегирования ошибок.
Шаблон реактивной архитектуры: само-восстанавливающиеся и само-наблюдаемые (self-monitoring) системы, которые могут автоматически конфигурироваться и восстанавливать себя.
Как определить текущую загрузку канала событий без потребления всех событий? Отдельный сервис (event monitor) может отслеживать количество сообщений, которое скопилось в очереди. Event monitor возможно реализовать для AMQP (RabbitMQ), ActiveMQ, JMS. Получая статстику о количестве потребителей, сообщений в очереди, загрузке CPU, тредов - мы можем реактивно влиять на количество ресурсов.
Как мы можем быть уверены в своевременном и консистентном ответе, когда наша система растет? Иногда не требуется сохранять порядок всех сообщений в очереди, но требуется сохранять порядок сообщений внутри конкретного контекста. Единый обработчик событий (event dispatcher) можно разделить на несколько "тред-делегатов", которые будут обрабатывать только конкретные сообщения из нужных контекстов, соблюдая порядок.
"Корпоративный архитектор" может работать не только с огромными транснациональными компаниями, но и локальными крупными компаниями, небольшими фирмами и даже с группами команд. Стратегия бизнеса и операционная модель формируют потребности бизнеса; бизнес-операции, ИТ-системы и инфраструктура формируют возможности ИТ. Задача корпоративного архитектора - совместить эти две сущности.
Пример: моя личная цель - пробежать марафон; оценка возможностей - стиль жизни, фитнесс, способности. Между целью и возможностями есть разрыв. Чтобы его устранить "архитектор" составляет план тренировок. Аналогично работает корпоративный архитектор с потребностями бизнеса и возможностями ИТ и инфраструктуры.
Задачи корпоративной архитектуры:
- обеспечить стратегическое архитектурное видение и направление;
- лидировать архитектурные трансформации и организационные изменения;
- проверять, что ИТ возможности удовлетворяют потребности бизнеса;
- налаживать управление архитектурой и процессами;
- распространять цели, метрики и ценности по всей организации.
Задача архитектора: определить куда идти и какими шагами.
Модельно-ориентированный подход - традиционный в enterprise arcthirecture. Моделирование отвечает на вопрос: "Что мы имеем в настоящий момент?", затем следует стадия инициатив, которые отвечает на вопрос "Что мы хотим сделать?". Следующая стадия - roadmap, "Как мы этого достигнем?". Далее - коммуникации, "Каков наш прогресс?". Идея: "сначала модель, затем задавай вопросы".
Особенности: общий процесс/состояние хорошо документировано, доступна идентификация инициатив "сверху-вниз" и "снизу-вверх", велики усилия на создание моделей, модели редко отражают актуальное состояние (быстро устаревают)
Пример использования модельно-ориентированного подхода: Zachman Framework.
Инициатива (цель) - отвечает на вопрос "Что мы хотим сделать?"; после этого идут этапы моделирования, roadmaps, коммуникации и отслеживания прогресса. Главное отличие от модельно-ориентированного подхода, что мы строим модели "по запросу", если нам это необходимо. В итоге, подход быстрее, чем модельно-ориентированный; все инициативы идут "сверху-вниз", от бизнеса; переиспользование и синхронизация модель - очень сложная задача (модели делаются под конкретную цель и не переиспользуются по умолчанию); общая картина компании не видна.
TOGAF: бизнес-драйверы и цели (инициатива) и бизнес возможности (capability) соединияются с помощью ADM (architecture develope methodology).
52. Modern approach
Проблема традиционных подходов (как модельно, так и инициативо-ориентированного): старые подходы созданы для ситуации, когда имеется текущее состояние, будущее состояние и подготавливается план миграции. Однако, план миграции как правило занимает много времени, не учитывает изменчивости окружающей среды, часто понимание как достичь будущего состояния не всегда понятно; обычно недостаточно деталей, чтобы точно проработать план миграции.
Современные подходы:
- инкрементальный - фокусируется на малых изменениях, которые неприрывно меняют текущее состояние системы и в конечном счете приведут к достижению целей;
- ценностно-ориентированный - все архитектуреные усилия (efforts) ограничиваются в контексте специфичных бизнес ценностей и обоснований (например, снижение расходов, увеличение скорости поставки, увеличение удовлетворенности пользователей, увеличение количества пользователей, стратегическое позиционирование), все, что мы делаем, сразу же относится к конкретной бизнес-ценности (или мы этого не делаем);
- адаптивный подход - игнорирует будущее состояние системы и фокусируется на создании высокоадаптивной системы, которое может удовлетворить текущие бизнес-потребности.
Транзакции в микросервисах не поддерживают ACID-гарантии. Сага фактически развернется в конечный автомат (state machine) с сохранением состояние после каждого шага распределенной транзакции. В ролике есть примеры аннотация для java.
Книги про архитектуру ПО (обзор сделан в марте 2019 года):
- James McGovern "The Practical Guide to Enterprise Architecture" (2003)
- Richard Monson-Haefel "97 Things Every Software Architect Should Know" (2009)
- Jeanne Ross, Peter Weill, David Robertso "Enterprise Architecture as Strategy" (2006)
- Richard Hunter and George Westerman "The Real Business of IT" (2009)
- Colin Powell "My American Journey" (2003)
ADR служит для хранения всех архитектурно значимых решений, которые затрагивают структуру, нефункциональные требования, зависимости, интерфейсы. ADR это короткий текстовый файл (не более 2 страниц), один файл на одно решение. ADR содержит пять основных секций: заголовок, статус (предложено, одобрено, отклонено), контекст решения (описание проблемы), решение (описание решения), изменение контекста после принятия решения (плюсы и минусы).
Шаблон "Скорая помощь" нужен в ситуации, когда некоторые запросы более приоритетные, чем другие. Варианты реализации: внедрение очередей с приоритетами - плохая реализация, которая может оставить обработку обычных, низкоприоритетных запросов; внедрение отдельной "высокоприоритетной" очереди - позволит настраивать объем обработки из обычной и приоритетной очередей; внедрение "высокоприоритетной" очереди и отдельного выделенного сервиса для её обработки.
Закон Деметры - принцип наименьшего знания, сервис или компонент должен обладать минимальными знаниями о других компонентах. "Не говори с незнакомцами, позволяй обращаться к тебе только твоим друзьям". Следование закону Деметры приводит к снижению связности между компонентами.
Сейчас все сертификации для России закрыты.
Отказ от прямых запросов (полный переход на очереди сообщений с фиксированным контрактом) даст возможность построить систему с нулевой связностью. Минусы подхода: нет контроля за процессом (workflow control) - мы не знаем, что происходит с процессом обработки заявки; нет обработки ошибок - ошибки остаются в своих сервисах; нет консистентности данных; нет управления состоянием транзакции.
Trade-off при использовании gRPC:
- За счет применения HTTP/2 и сжатия protocol buffers взаимодействие между сервисами быстрее
- За счет создания на стороне сервера gRPC-сервера, а на стороне клиента gRPC-стаба, повышается связанность между сервисами
- Использование grpc lb (load-balancer) на стороне клиента, отдельного сервиса/side-car
Широковещательные топики (broadcast topic) решают проблему масштабирования паттерна "публикатор/подписчик". Преимущества подхода "для каждого подписчика своя очередь": безопасность и контроль доступа к данным; скорость очистки топика не может быть выше, чем скорость чтения самого медленного подписчика; простота мониторинга и размера очереди.
Стратегия определяет всю структуру архитектурный команды и как стандарты принимаются и управляются в каждом юните/команде. Стандарты включают в себя технологические (фреймворки, базы данных, языки программирования и т.д.), архитектурные (документы и диаграммы, ADR), методологические (agile, lean и т.д.), процессные (PDR, release-процесс и т.д.)
Существуют централизованные стратегии, где стандарты принимаются enterprise архитектором (предписывающая, классическая альтернативная) и децентрализованные (распределенные - у каждого юнита могут быть свои стандарты; "durable interface" - стратегия каждого юнита принимается для всей компании) стратегии.
Предписывающая стратегия - предписывает, какие решения должны применяться разработчиками через установку набор общих стандартов, применяемых во всей организации. Плюсы: уменьшает сложность, уменьшает скорость принятия решения (все стандарты уже приняты), увеличивает переиспользование решений из разных отделов, низкие расходы. Минусы: не подстраивается под конкретные проблемы, сложно достичь консенсуса в масштабах компании, разработчики демотивируются из-за навязанных решений, требуется строгий контроль.
Классическая стратегия альтернатив предписывает, какие решения должны применяться разработчиками из множества одобренных стандартов, применяемых в организации. Плюсы: исполнитель может выбрать подходящий инструмент для работы, больше контроля над выбором решения, рост удовлетворения у разработчиков. Минусы: увеличивает время проектирования (больше прототипов, рассмотрение альтернатив), выбор решения может быть неудачным; высокие суммарные затраты (по сравнению с предписывающей стратегией, больше лицензий и т.д.).
Распределенная стратегия предполагает делегирование выбора решений и определения стандартов на уровень изолированных бизнес-подразделений с минимальными общими корпоративными стандартами. Как правило, общие корпоративные стандарты устанавливаются в области безопасности и использования hardware-решений. Образуются слои стандартов: стандарты "ядра" (общие для всей корпорации), стандарты бизнес-юнита, стандарты команды. Преимущества: каждый отдел может выбрать наиболее подходящий инструмент, минимум глобальных стандартов, большая удовлетворенность исполнителей. Недостатки: тяжелая синхронизация, очень высокая стоимость, сложно контролировать затраты, сложно управлять стандартами.
Делегирование выбора решений и определение стандартов на уровень изолированных бизнес-подразделений. Корпоративные стандарты - будут определятся только теми стандартами, которые описывают взаимодействие бизнес-подразделений между собой (только interface). Каждая бизнес-линия полностью автономна в принятии своих решений и стандартов. Преимущества: каждый отдел выбирает наиболее подходящий инструмент, бизнес контролирует свои стандарты, синергия между бизнес-юнитами (за счет интерфейса). Недостатки: разработка интерфейсов между отделами (очень сложная), очень высокая стоимость, сложно контролировать затраты.
Изучение двух примеров для выбора архитектурной стратегии на практике. Пример 1: большая компания с двумя сегментами (b2b и b2c), производственная и финансовая система единые во всей компании, но обслуживание клиентов и система заказов у каждого отдела своя. Выводы: большая стабильная компания, не требует больших изменений и инноваций, хорошие отношения между отделами, автономность сегментов, централизованная система для финансов и производства, большая рыночная доля, стабильная база клиентов, минимальная различность. Для такой компании лучше выбрать централизованную систему (распределенные будут дороже) и классическую (так как различие отделов невелико).
Второй пример на компанию с двумя бизнес-процессами (консультирования и разработка и продажа ПО), с двумя головными офисами (в Европе и США), быстро растущий бизнес и высокая готовность к изменениям, разнообразие законодательства. Для такой компании не подойдет централизованная классическая стратегия (недостаточно гибкая). Распределенная стратегия с гибкими интерфейсами - лучший выбор.
Автоматизация соблюдения архитектурных решений с помощью ArchUnit (Java) или NetArchTest (C#). Тесты, которые позволяют проверить связность пакетов/сборок между собой.