Дмитрий Голых
Micro Services Architecture
В этой статье вы получите ответы на три ключевых вопроса:

  1. Что такое архитектура программного обеспечения?
  2. Почему существует несколько разновидностей архитектуры программного обеспечения?
  3. Какие существуют основные характеристики микросервисной архитектуры и почему они важны?
Архитектура ПО.
Понятие архитектуры
Исторически понятие архитектура ассоциируется прежде всего со строительством зданий. В строительстве архитектура сжато определяет все аспекты восприятия сооружения: насколько оно гармонично вписывается в окружение, как выглядит изнутри и снаружи, насколько это сооружение гибко к развитию, какие у него будут коммуникации и т. д.

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

Давайте рассмотрим трансформацию бизнеса и IT-ландшафта бизнеса на примере организации «Цветочный магазин». Представим, что мы открыли небольшую цветочную лавку. В начале пути развития бизнеса мы сами стоим за прилавком, покупаем материалы, работаем с клиентами, осуществляем продажи и т. д.
Со временем клиентов становится больше, и, так или иначе, даже для такого маленького бизнеса появляется необходимость иметь своё приложение. Например, это может быть ERP-система (Enterprise Resource Planning — планирование ресурсов предприятия) для ведения бухгалтерии, кадрового учёта, логистики и продаж. На первоначальном этапе нам будет достаточно монолитного приложения.
Монолитная архитектура
Монолитное приложение — тип двухуровневой (также называют двухзвенной) архитектуры. При двухуровневой архитектуре приложение разбито на два слоя.

  1. На первом слое находится визуальный интерфейс (UI — User Interface), предназначенный для удобства использования приложения и некоторой валидации данных.
  2. Второй слой — слой хранилища данных. На этом слое кроме хранилища существует некая бизнес-логика, например: бухгалтерия, составление отчётности и т. д. Логика может быть, например, написана на каком-либо транзакционном языке, в зависимости от конкретной СУБД (система управления базами данных).
При необходимости такое приложение можно масштабировать путём увеличения мощности сервера, на котором инсталлировано приложение — «вертикальное масштабирование».
В ходе расширения бизнеса (новые точки продаж, складские учреждения и взаимодействие с ними, франчайзинг) мы понимаем, что продолжать развивать монолитное приложение становится сложно: трудно обеспечивать взаимодействие по сети между экземплярами пользовательского интерфейса и базой данных, бизнес-логика начинает работать медленнее и т. д.

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

Таким образом, мы подходим к другому типу архитектуры программного обеспечения — сервис-ориентированной архитектуре (СОА, SOA — service-oriented architecture).

СОА (сервис-ориентированная архитектура) — многослойная (три или более уровня) архитектура, каждый слой которой отвечает за определённую «обязанность»:

  • 1 слой — пользовательский интерфейс, зачастую веб-интерфейс
  • 2 слой — бизнес-логика: расчёты, агрегация данных и т. д.
  • 3 слой — база данных (хранилище)
Сервис-ориентированная архитектура

Упрощённая схема сервисно-ориентированной архитектуры
СОА позволяет локализовать функционал в некоторых функциональных блоках — сервисах. Это позволяет без критичного влияния на всю систему поставлять сервисы партнерам, или, наоборот, в случае необходимости отказаться от него и встроить другое решение. Такая гибкость достигается путем использования API или других транспортных инструментов.

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

Цифровой рынок является «скоростным». Это значит, что для выхода на рынок решений необходимо меньше времени, чем для того, чтобы построить физический магазин.

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

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

На данный момент это очень востребовано и существует множество различных сервисов: Yandex Cloud, Amazon Web Services, Microsoft Azure и т. д.

Использование такого типа архитектуры позволяет регулировать масштабируемость системы, уменьшить вероятность возникновения регрессионных ошибок и оптимизировать затраты.

Схемы различных типов архитектурных решений
Микросервисы.
Основные характеристики

Микросервисы — это небольшие автономные совместно работающие сервисы.
Можно выделить следующие основные характеристики МСА:

  • Максимальная независимость и автономность
  • Реализация подхода «умные сервисы и глупые каналы» (smart endpoints and dumb pipes) при микросервисном взаимодействии
  • Поддержка DevOps подходов CI (Continuous integration, Непрерывная интеграция) и CD (Continuous delivery, Непрерывная доставка)
  • Гибкая масштабируемость
  • Нацеленность на концепцию децентрализации управления данными

Рассмотрим подробнее каждую характеристику.
Независимость и автономность
Данное свойство достигается правильным разбиением микросервисов. Существует множество способов микросервисного разбиения, а также большое количество консалтинговых компаний, предлагающих свои способы: Accenture, McKinsey&Company, Gartner и т. д. Так или иначе, практически все способы ориентируются на подход DDD (Domain-driven design, Предметно-ориентированное проектирование).

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

2. Определение ограниченных контекстов предметной области. В нашем примере с цветочным магазином, можно выделить следующие крупные блоки функциональности: логистика, бухгалтерия, онлайн-покупки, личный кабинет пользователя и т. д. В каждом из крупных блоков мы определяем бизнес контексты. Например, в логистике это могут быть взаимодействие с контрагентами по закупке, транспортировка, складирование и т. д. Контекст ограничивается конкретной пользой (например, польза контекста склада — актуальный учёт количества и состояния продукции).
3. Применение тактических шаблонов DDD в рамках выделенного ограниченного контекста. Это позволит определить сущности, с которыми будет взаимодействовать система внутри контекста, а именно:

а. агрегаты, которые могут совершать какие-либо действия
b. события внутри контекста
c. команды
.
4. Идентификация микрослужб на основании результатов предыдущего шага.

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

В результате разбиения функционала по контекстам реализуется свойство независимости и автономности. Это проверяется следующим образом: мы представляем, что один из контекстов перестаёт физически существовать. Если в таком случае система сможет функционировать, значит, разбиение функционала было выполнено правильно.
«Умные сервисы и глупые каналы»

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

Например, ESB (Enterprise Service Bus, сервисная шина предприятия). Данная шина выносит наружу API, которые могут вызывать различные системы, и за API реализует логику вызова. Этот подход хорошо зарекомендовал себя благодаря тому, что:

  • Позволяет сделать окружение более гибким к изменениям
  • Реализуется на общепризнанных стандартах
  • Содержит большое количество конфигураций для интеграции

Минусы шины:
  • Сложность реализации (большое количество служб и компонентов)
  • Требуется большое количество ресурсов для разработки и развития

В ESB реализован подход «умный канал и глупые сервисы» (умный канал — шина ESB, глупые сервисы — конечные системы).

Схема шины ESB

В противовес ESB существует подход «умные сервисы и глупые каналы», используемый в МСА.
В виде каналов в данном подходе выступают различные брокеры:

А в виде сервисов — шлюзы (API Gateway), которые скрывают за собой реализацию и выносят наружу для взаимодействия API.

Рассмотрим плюсы и минусы данного подхода.

Подход «Умные сервисы и глупые каналы»
Поддержка подходов DevOps

Как было упомянуто ранее, при проектировании МСА должны поддерживать два DevOps-подхода:

Эти процессы взаимодействуют друг с другом — непрерывная доставка идёт следом за непрерывной интеграцией.

Непрерывная интеграция состоит из следующих этапов:

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

Непрерывная поставка состоит из следующих этапов.

  1. Выпуск. На данном этапе образы сервисов упаковываются в контейнеры и размещаются в репозитории продукта.
  2. Установка. Репозиторий, например Docker Hub, на данном этапе осуществляет перенос сервисов на стенды.
  3. Операционная работа. На данном этапе осуществляется UI-тестирование, развёртывание системы в staging-окружении и production-окружении.

Схема непрерывной интеграции и непрерывной доставки
Все эти процессы нацелены на сокращение времени от первичной идеи до выхода продукта на рынок.
Гибкая масштабируемость

«Данная характеристика достигается применением соответствующих технологий, а именно — контейнеризацией, например, в docker-контейнер.

При использовании данной технологии микросервисы упаковываются в docker-контейнеры, которыми управляет специальная служба (например, Kubernetes или Consul). Для того, чтобы микросервисы могли «жить» в разных копиях и их экземпляры создавались автоматически, служба управления контейнерами содержит вспомогательную службу регистрации микросервисов. Вот как это работает.

  1. Когда реализуется микросервис, в службе регистрации создаётся соответствующая запись, в которой прописываются виртуальный API этого микросервиса и ресурсы, с которыми он работает.
  2. В случае возникновения пиковой нагрузки система управления контейнерами сможет определить нагрузку микросервисов и автоматически развернёт новый экземпляр микросервиса, нагрузка которого критически увеличилась.
  3. Служба регистрации перенаправит пограничный сервис (GateWay) к нужному микросервису.

При правильно выделенных ресурсах и грамотном разбиении системы на микросервисы, «выживаемость» системы и возможности масштабируемости колоссально возрастают по сравнению с другими архитектурными подходами (монолитная архитектура и сервис-ориентированная архитектура).

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

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

Децентрализация также обеспечивает независимость от технологического стека: не только каждый микросервис может быть написан на своём языке, но и база данных может быть именно та, которая подходит для конкретного микросервиса (реляционная, документо-ориентированная и т. д.)

Децентрализация управления данными
Подведём итоги

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

Основные плюсы МСА:

  1. Микросервисы скрывают подробности внутренней реализации системы, предоставляя API на уровне пограничных сервисов (GateWay). Это делает систему более гибкой, позволяет заменять сервисы и части системы без риска потери функционала.
  2. Применение практик DevOps позволяет сократить время от идеи создания системы до выхода на рынок.
  3. Децентрализация обеспечивает независимость от технологического стека.
  4. Применение МСА позволяет изолировать сбои внутри микросервиса, что позволяет сохранять стабильность системы.

Плюсы МСА рождают также определенные минусы:

  1. МСА требует правильного выделения бизнес-задач и грамотного проектирования системы.
  2. Необходимо уметь правильно разрабатывать API управлять интерфейсами взаимодействия.
  3. МСА требует всестороннего наблюдения за системой.
  4. Изоляция сбоя может затруднить нахождение источника проблемы.

Автор выделяет для себя следующие правила:
  1. Микросервисы нужны тогда, когда существует вероятность внезапного возникновения пиковой нагрузки в короткий промежуток времени.
  2. Микросервисы нужны тогда, когда необходимо обеспечивать быструю доставку нового функционала.
Вопросы и ответы
Вопрос:
Как бороться за транзакционность микросервисных приложений?
Ответ:

Для этого существует очень много подходов. Самый простой — разбить микросервсы по уровням транзакции, чтобы вся транзакция была реализована в одном микросервисе. Когда мы поймём, что некоторые куски функционала в микросервисе часто изменяемы и их лучше вынести в соседний микросервис, чтобы обеспечить стабильность первичного микросервиса, можно реализовать транзакционность через паттерн «Saga».

Правила взаимодействия микросервисов в асинхронном режиме
В данном случае всё зависит от конкретной ситуации. Основные подходы:

  • Использование GateWay
  • Использование Service mesh
  • Событийная архитектура взаимодействия Event-driven
Вопрос:
Что изучить для понимания принципов построения МСА? Какие базовые знания и навыки надо иметь?
Ответ:

В первую очередь необходимо хорошо изучить бизнес, для которого реализуется МСА, чтобы верно определить контексты. Далее всё зависит от используемого технологического стека.

Из обязательного:

  • Контейнеризация в docker-контейнеры и среды управления контейнерами
  • Службы регистрации микросервисов
Вопрос:
Какого масштаба продукты имеет смысл декомпозировать на микросервисы?
Ответ:
Декомпозировать можно продукты любого масштаба. Главное — понимать, какие плюсы вы хотите получить. Это необязательно должно быть web-приложение, микросервисы могут дать безопасную декомпозицию кода и обеспечить слабосвязность модулей решения.
Вопрос:
В какой момент приходит осознание того, что нужно переписать систему на микросервисах?
Ответ:
В тот момент, когда текущая архитектура решения начинает приносить проблемы: например, не получается быстро разработать новый функционал без влияния на текущий. Также, когда появляется требование выдержать пиковую нагрузку или когда необходимо по каким-то причинам изолировать блоки приложения друг от друга.
Вопрос:
Что необходимо знать аналитику об архитектуре? Необходимо ли уметь проектировать архитектуру?
Ответ:
Так или иначе любой сотрудник в IT, особенно аналитик, должен иметь базовые знания об архитектуре.
Вопрос:
Как службы безопасности относятся к облачным сервисам?
Ответ:
Всё зависит от функционала, который вы реализуете. Например, если вы храните персональные данные пользователей, их обработка и хранение должны осуществляться только на территории РФ (Федеральный закон «О персональных данных» от 27.07.2006 N 152-ФЗ).

Если сервис не связан с личными данными пользователей и контур облачного провайдера защищён в соответствии с рекомендациями службы безопасности, то никаких проблем возникнуть не должно.
Вопрос:
Как решается вопрос синхронизации в МСА, если у каждого сервиса свои данные?
Ответ:

Существует универсальные правила построения уровня кэшированных данных.

  1. Если мастер-система данных является активной стороной, она может событийно через Apache Kafka или брокер сообщений выдавать изменяемую часть данных и мы будем содержать у себя ограниченную модель данных, которые нам нужны. Далее будем отслеживать события на изменение хранимых атрибутов от мастер-системы.

  2. Если мы активная сторона, то мы должны иметь срок доверия к данным. Например, раз в час делать вызов данных из мастер-системы и сравнивать с нашими данными и делать изменения, если они были.

Подходов может быть много, всё зависит от конкретной задачи.

Имеют место ситуации, когда между системами создаётся межсервисный слой кэшированных данных (In-Memory Data Grid или In-Memory Database), который служит либо только для чтения, либо только для записи.
Вопрос:
Где можно ознакомиться с тактическими DDD-паттернами?
Ответ:
Каждый человек воспринимает любой материал по-своему, лучше всего посмотреть много разных источников. DDD — непростая тема, сначала нужно изучить теоретическую базу (Eric Evans. Domain-Driven Design: Tackling Complexity in the Heart of Software и Vaughn Vernon. Implementing Domain-Driven Design 1st Edition) и далее смотреть тематические материалы на Хабр и Youtube и других платформах.
Вопрос:
Рекомендации по транспорту большого количества данных между микросервисами?
Ответ:
Использование стриминговых систем, например, Apache Kafka.
Дмитрий Голых
solution-архитектор
  • 8 лет стажа в IT
  • Прошел путь от front-end разработчика до solution-архитектора.
  • Занимался аналитикой, full-stack разработкой.
  • Работал в финансовой сфере — обеспечивал IT-поддержку банковских учреждений.
Подписаться на новые статьи