Статьи

От монолита к микросервисам: проблемы, риски, практические советы

Марин Путникович, главный архитектор «Лиги Ставок»
Зачем переходить на микросервисную архитектуру (MSA), какие сложности могут возникнуть в процессе, как на практике спланировать план «релокации» и почему решение об уходе с монолита гораздо больше зависит от принципов и культуры компании, чем от трендов в ИТ-индустрии, — об этом и многом другом мы расскажем в данной статье.
Переход на микросервисы — это не просто технологическое решение. Это шаг к созданию более гибкой и отзывчивой организации, конечная цель которой — позволить командам быстро и бесшовно внедрять функции в производство.

Зачем переходить на микросервисы

Как всякая успешная миграция, успешный переход на микросервисы — это не только бегство от чего-то, но и приход к чему-то. Убедитесь, что, планируя переход, вы преследуете обе цели, а не только одну из них.
Минусы монолита, которые могут стать поводом к переходу на микросервисы (бегство от):
  1. Времязатратность: даже небольшие обновления требуют развертывания всего приложения
  2. Трудности с тестированием и обслуживанием: со временем монолитные приложения становятся сложнее
  3. Единообразие стека: единый технологический стек во всем приложении может ограничивать гибкость.
  4. Единая точка отказа: плотное сцепление компонентов создает риск системных сбоев из-за проблем в отдельных компонентах.
  5. Проблемы масштабируемости.
Эти проблемы негативно влияют на несколько архитектурных метрик, таких как:
Низкая частота запуска новых функций или возможностей (Deployment Frequency). Невысокие показатели развертывания свидетельствуют о недостаточной гибкости и эффективности процесса разработки.
Длительное время внесения изменений (Lead Time for Changes). Если от постановки задач бизнесом до доступных пользователю изменений проходит слишком много времени, это значит, что системе не хватает гибкости в удовлетворении бизнес- или NFR-требований.
Высокая частота аварий, вызванных выкладкой изменений (Change Failure Rate). Высокие показатели указывают на возможные проблемы качества кода, тестирования или развертывания.
Микросервисы, по определению, представляют собой стиль проектирования, при котором программные системы создаются в виде коллекций небольших, развертываемых и слабо связанных сервисов, каждый из которых представляет определенные бизнес-возможности. По сути, микросервисы можно рассматривать как усовершенствованную версию архитектуры SOA, сосредоточенную на узкой функциональности с четко определенными интерфейсами.
Ключевые характеристики микросервисов:
  • Каждый сервис сосредоточен на одной бизнес-возможности (Single Responsibility).
  • Независимость: сервисы работают, развертываются и масштабируются независимо.
  • Распределенная разработка: гибкость разработки с различными технологическими стеками.
  • Изоляция ошибок: системная устойчивость поддерживается путем изоляции сбоев в отдельных сервисах.
  • Автономные операции: небольшие команды могут контролировать весь жизненный цикл каждого сервиса.

Кто решает переходить на микросервисы?

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

Запуск миграции

При рассмотрении миграции на микросервисы основным шагом является формулировка четкой стратегии миграции. Эта стратегия служит как указанием, так и проектом, определяя траекторию и объем миграции.
В центре стратегии миграции находятся два ключевых вопроса: почему и когда.
Цели миграции должны четко объяснять логику перехода на микросервисы. Ключевые моменты включают:
  • Ожидаемые преимущества от внедрения микросервисов.
  • Соответствие миграции общим бизнес-целям.
  • Проблемы в монолитной архитектуре, которые миграция пытается решить.
Определите объем миграции. Будете ли вы рефакторить в микросервисы весь монолит или только его часть? Как будут декомпозированы микросервисы — на основе бизнес-возможностей, доменно-ориентированного проектирования или другого метода?
Это будет одним из самых трудных и важных решений.
О чем важно помнить перед началом миграции:
  1. Декомпозиция не обязана быть микро. Чрезмерно дробные сервисы могут привести к трудностям понимания, управления и отлаживания системы.
  2. Микросервис не означает микроресурсы. Функционально узкий сервис может быть очень ресурсозатратным.
  3. Домен — это главное. Микросервисы служат домену, а не просто являются контейнером для функциональности.
  4. Асинхронность — важнейший принцип. Связность — ваш враг, уменьшите ее, насколько это возможно.
Кстати: один из наиболее удобных подходов к проектированию — это DOMA (Domain Oriented Microservice Architecture). Этот дизайн позволяет преобразовывать сложные архитектуры микросервисов в наборы организованных, адаптируемых и многослойных компонентов. У каждого домена в DOMA есть свой уникальный «шлюз» — единая точка доступа. Каждый — независим, без жестко закодированной логики или моделей данных из других домен.

Начало программирования

Роль инфраструктуры

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

Облако и Kubernetes как основы современной инфраструктуры

Облако (Cloud). Облачные вычисления позволяют нам обращаться к вычислительным мощностям, размещенным в современных дата-центрах облачных провайдеров, используя Интернет.
Облачное решение может быть частным, публичным, гибридным или многооблачным.
Публичное облако (Public Cloud). Это выделенная облачная среда, где все ресурсы предназначены исключительно для одной организации.
Плюсы: усиленная безопасность и контроль.
Частное облако (Private Cloud). Ресурсы размещаются на территории поставщика услуг и разделяются между несколькими клиентами.
Плюсы: масштабируемость и экономическая эффективность.
Гибридное облако (Hybrid Cloud). Это сочетание частных и публичных облаков.
Плюсы: сочетание преимуществ облаков обоих типов.
Многооблачность (Multi-Cloud). Использование нескольких облачных сервисов.
Плюсы: можно смешивать общедоступные, частные или гибридные облака в зависимости от конкретных потребностей.
Kubernetes. Kubernetes (K8s) занимает видное место в ландшафте оркестровки контейнеров. Его появление обещало упростить развертывание контейнеризованных приложений, предоставляя единую платформу для управления, масштабирования и обеспечения устойчивости приложений.
Однако, как и многие мощные инструменты, сильные стороны Kubernetes также являются его сложностями. Для разработчиков, особенно тех, кто привык к более простым парадигмам развертывания, погружение в Kubernetes может быть сложным, как изучение нового языка. Терминологии — pods, services, replicasets, configmaps и многие другие — формируют лексикон, который требует времени и усилий для освоения. Сложные конфигурации YAML иногда становятся источником раздражения, и незначительные неправильные конфигурации могут привести к серьезным проблемам во время выполнения.
Кроме того, решение о принятии Kubernetes не всегда движимо чисто технической необходимостью. Иногда это диктуется трендами индустрии, давлением сверстников или предполагаемой обязанностью идти в ногу с «последним и лучшим». Это может привести к сценариям, когда Kubernetes вводится в среды, где его возможности не используются полностью или, что хуже, где его сложности затмевают его преимущества.
Кому подходит K8s? Бизнесам, стремящимся к гибкости, масштабируемости и устойчивости. Для тех, кто ориентируется на будущее, где требования к приложениям непредсказуемы и постоянно меняются.
Выбор правильной топологии — главное, что нужно знать при работе с K8s.
Конфигурация K8s может быть базовой (Single Master — Multiple Workers). Один узел-мастер в ней управляется несколькими узлами. При этом есть риск, что при отказе мастер-узла нарушится работа всего кластера. Более устойчивая к отказам система — Stacked etcd. Мастер-узлов здесь уже несколько, и если один выходит из строя, оставшиеся могут обеспечить работу кластера. В External etcd Cluster вместо запуска etcd на мастер-узлах используется отдельный набор узлов, предназначенных для работы кластера etcd. Она также отличается достаточно высокой устойчивостью. Для критически важных приложениях подойдет самая надежная многомастеровая конфигурация с etcd, распределенным по нескольким зонам или регионам — Multi-Region/Multi-Zone Setup.

CI/CD

В области современной разработки непрерывная интеграция и непрерывная доставка/развертывание (CI/CD) занимают особое место.
Хотя мы говорим о нем, как об одном целом процессе, есть две части CI/CD, и их следует рассматривать как два отдельных, независимых процесса.
— CI (Continuous Integration) — процесс, который оценивает последние изменения кода, чтобы определить, требует ли создание нового артефакта.
Обычно эти артефакты рассматриваются как кандидаты на релиз.
Благодаря CI, проблемы интеграции выявляются своевременно. Количество шагов, которые вы можете включить в свой CI-конвейер, почти бесконечно. Это может быть, например, сборка, статический анализ кода, юнит-тестирование, интеграционные тесты, контейнеризация и т. д. Расти рекомендуется с базовых шагов.
— CD (Continuous Delivery/Deployment) — способность выпускать обновления программного обеспечения в любой среде, в любое время автоматически и повторимо. Существует в двух формах:
Непрерывная доставка (Delivery): этот подход гарантирует, что программное обеспечение всегда находится в состоянии, пригодном для развертывания.
Непрерывное развертывание (Deployment): позволяет автоматически выпускать каждое изменение, которое проходит через конвейер, непосредственно в производственную среду без вмешательства человека. Но как и в случае с CI, мы рекомендуем здесь начинать с малого и расти по мере роста компетентности.

Несколько советов по работе с кодом

Работа с кодом — вещь очень индивидуальная. У каждого специалиста есть свои наработки и предпочтения. Вот несколько субъективных правил, которые можно взять на вооружение.

Правило 1. Разработайте строгие рекомендации по кодированию

Имеется в виду множество стандартов: от соглашений о наименовании классов и объектов до конкретных мест в вашей кодовой базе, где должна находиться бизнес-логика, DTO, интерфейсы и т. п. Помимо простого наименования переменных, полезно использовать разные суффиксы, адаптированные к различным типам приложений и средам выполнения.

Правило 2. Разделяйте код и инфраструктуру

В процессе своей работы ваше приложение будет взаимодействовать с множеством компонентов инфраструктуры, включая базы данных, Redis, Kafka, RabbitMQ, Prometheus, LogStash, K8s-пробы и др. Чтобы обеспечить единообразие использования и избежать различных реализаций, создайте набор стандартизированных библиотек для этих взаимодействий.

Правило 3. Держите ваш CI-ĸонвейер вне вашей ĸодовой базы

Как правило, CI-конвейер требует код для создания артефакта, чтобы избежать ошибок, лучше разместить этот код в отдельном репозитории, отличном от кода приложения. Это позволит усовершенствовать и изменять конвейер не влияя на основной код приложения. Такое разделение поможет минимизировать потенциальные проблемы, такие, например, как непреднамеренное глобальное переименование или случайные клики.

Cloud Native

Все, о чем мы говорили выше, сводится к одному термину, который стабильно набирает обороты в мире разработки и развертывания программного обеспечения — это Cloud Native. В своей основе, Cloud Native относится к проектированию, реализации и развертыванию приложений таким образом, чтобы максимально использовать преимущества облака. Вместо того, чтобы просто переносить традиционные приложения в облако, Cloud Native включает в себя разработку приложений специально для облачных сред
Основные принципы Cloud Native:
MSA: вместо монолитных приложений, Cloud Native способствует разработке микросервисов.
Контейнеризация: контейнеры инкапсулируют приложение и его зависимости в постоянной среде. Это гарантирует, что приложение ведет себя одинаково, независимо от того, где запущен контейнер, будь то локальная машина разработчика или облачная производственная среда.
Continuous Delivery: поскольку приложения могут состоять из множества контейнеров, на помощь приходят инструменты динамической оркестровки, такие как Kubernetes.
Устойчивость и избыточность: системы проектируются так, чтобы быть устойчивыми к сбоям. Сбои будут происходить, но эти сбои предвидены, что позволяет системе элегантно справляться или восстанавливаться после них.
Децентрализованное управление данными: с микросервисами каждый сервис управляет своими данными и отвечает за свою собственную базу данных.
Immutable Infrastructure: после развертывания компоненты инфраструктуры не меняются. Вместо этого обновления производятся путем замены компонентов, а не их модификации.
Наблюдаемость: динамический и распределенный характер упрощает наблюдаемость и дает представление о состоянии и поведении системы.
Кому подходит Cloud Native:
  • Организациям, работающим с приложениями, которые должны быстро масштабироваться в ответ на изменяющиеся нагрузки.
  • Бизнесам, проходящим цифровую трансформацию, нацеленным на быстрые циклы инноваций.
  • Компаниям, которым требуется высокая доступность и устойчивость, гибкость, сокращение инфраструктурных затрат и ускорение времени выхода на рынок.
  • Предприятиям, создающим приложения с нуля без ограничений устаревших систем,
Кому не подходит Cloud Native:
  • Организациям, использующим устаревшие приложения, которые имеют стабильные и предсказуемые потребности и не оправдывают издержек миграции.
  • Небольшим проектам или приложениям с коротким сроком службы.

Миграционные паттерны

Мигрировать с монолита на микросервисы можно несколькими способами.
Модель Strangler Fig: данный паттерн заключается в поэтапной замене частей монолита микросервисами. Вы начинаете с выделения конкретного функционала в вашем монолите, создаете новый микросервис для предоставления этого функционала и направляете запросы к новому сервису вместо монолита.
Плюс: позволяет снизить риски миграции и распределить временные усилия разработчиков.
Parallel Run: этот паттерн предполагает параллельный запуск нового микросервиса со старой монолитной системой и сравнение их результатов.
Плюс: позволяет проверить, что ваши новые микросервисы работают правильно, не отключая старую систему.
Branch By Abstraction: это добавление абстрактного слоя в монолите, который может направлять запросы либо к старому коду, либо к новому микросервису.
Плюс: позволяет постепенно переносить трафика от вашего монолита к вашим микросервисам
Change Data Capture (CDC): заключается в мониторинге базы данных на предмет изменений, а затем публикации этих изменений в виде событий, которые могут быть приняты другими сервисами.
Плюс: микросервисы могут оставаться в курсе изменений в монолите, не имея прямого доступа к его базе данных
Anti-Corruption Layer: включает в себя создание переводного слоя между вашим монолитом и вашими микросервисами.
Плюс: гарантия, что изменения в монолите не будут иметь негативного воздействия на микросервисы и наоборот.
Bubble Context: еще один паттерн для постепенной миграции, где вы создаете «пузырь» вокруг конкретной функции монолита.
Плюс: пузырь защищает новый микросервис от сложностей монолита.
Различные паттерны миграции могут помогать в вашем переходе, и, как правило, вопрос не в выборе только одного из них.

Главные принципы миграции

Сосредоточьтесь на новом. Начните с концептуализации новой бизнес-области. Только определившись с основными элементами нового сервиса, приступайте к работе с переходными компонентами и замене устаревших систем.
Изолируйте переходные компоненты. Переходные компоненты должны быть спроектированы как независимые сервисы. Их основная роль — быть посредниками, преодолевающими разрыв между старыми системами и новыми реализациями.
Держите логику перехода отдельно. Насколько это возможно, избегайте встраивания переходной логики в ваши новые сервисы.
Создайте структурированный план миграции. Это поможет снизить риски и постоянно мониторить прогресс, выявляя и устраняя ошибки и слабые места на ранней стадии.
Как еще снизить риски в процессе миграции:
  1. Стремиться к прозрачности. Каждое заинтересованное лицо должно иметь доступ к плану миграции.
  2. Обсуждать и пересматривать план в команде. В динамичном мире технологий способность к адаптации и сотрудничеству определяет успех сложных проектов.

Микросервисы и культура компании

Чтобы раскрыть весь потенциал микросервисов, необходима подходящая организационная культура.
Идеологические требования для работы с микросервисами:
  1. Ориентированный на рост образ мышления. Микросервисы процветают в компаниях, ориентированных на рост и совершенство.
  2. Готовность рисковать и инновировать. Если компания существует в режиме выживания, усилия по переходу к новой философии не будут иметь смысла.
  3. Техническая экспертиза на первом месте, управление на втором. Первое, что нужно микросервисам — это техническая экспертиза. Но следует учитывать, что не все талантливые разработчики предназначены для управления.

От эволюции программного обеспечения к культурной революции

Внедрение микросервисов требует преодоления идеологических проблем. Любые изменения в архитектуре программного обеспечения исходят из эволюции организационной культуры. Если культура компании готова к изменениям, результатом будет эффективная команда, продвигающая цифровую сторону бизнеса вперед.
О чем важно знать:
  1. Высококвалифицированные разработчики лучше проявляют себя в среде, которая поощряет индивидуальную свободу. В этом смысле традиционные централизованные архитектуры могут стать препятствием и косвенно подавлять инновации.
  2. Талантливый разработчик должен иметь возможность проявлять инициативу. Такие сотрудники часто мыслят глобально и вытягивают компанию вперед. Так, например, для Amazon и Netflix переход на микросервисы не был предварительно обдуманной бизнес-стратегией. Это решение было принято в ответ на предложение от их программных инженеров и операторов, которые стремились минимизировать неэффективность.
Как прийти к современной организационной культуре:
  • Стимулировать решение проблем: награждать за инновационные решения и снижать страх совершения ошибок.
  • Стимулировать творчество: организовывать хакатоны и другие мозговые штурмы для стимулирования свободного мышления.
  • Способствовать сотрудничеству: исследовать современные методы, такие как парное программирование, чтобы усилить командную работу.
  • Создавать сообщество: открыть исходный код некоторых из ваших инструментов и привлекать внешние сообщества, организовывая встречи.
  • Демонстрировать талант: организовывать технические доклады, предоставляя вашей команде платформу для обмена проектами или техническими новшествами.
  • Принимать и адаптироваться: инициировать проекты с нуля для тестирования новых технологий и методик.
  • Формировать разнообразную команду: разнообразие взглядов обогатит способность решать проблемы.
Постоянно внедряя эти практики, вы позиционируете свой бизнес не только как готовый к микросервисам, но и как магнит для лучших специалистов — знак прогрессивной, ориентированной на рост организации.
Разработка и продукты