Итак, возвращаемся к микросервисам. Начнём с основ: как концепция зародилась, какие проблемы решает и чем отличается от других решений. Дальше в спринте поговорим о принципах декомпозиции монолита, о лучших паттернах и DevOps-практиках микросервисной архитектуры.
Как появились микросервисы
Термин «микросервисы» появился в начале 2000-х годов. Идея возникла в результате эволюции уже существовавших практик разработки программного обеспечения. В первую очередь — сервис-ориентированной архитектуры (SOA).
Вот место микросервисов в хронологии появления архитектурных стилей:
Считается, что понятие «микросервисы» появилось благодаря Питеру Роджерсу. Джеймс Льюис и Мартин Фаулер подхватили идею в числе первых и приложили много усилий, чтобы объяснить концепцию и привлечь к ней внимание.
Там они описали микросервисы как способ разработки программного обеспечения, при котором приложения строят из множества небольших, независимых сервисов, каждый из которых выполняет одну бизнес-функцию. Микросервисы общаются между собой через легковесные механизмы, такие как HTTP API и сообщения.
В статье авторы также отметили, что крупные компании уже применяют этот подход. Например, такая архитектура у приложений Amazon и Netflix. Сами разработчики на тот момент считали свою архитектуру вариацией SOA.
Проблемы монолита
Микросервисы позиционируют как решение проблем монолита. Если приложение достаточно большое и сложное, монолит создаёт такие трудности:
Высокий риск ошибок. Изменения в одной части приложения могут непредсказуемо влиять на другие части. Из-за этого вырастает вероятность возникновения ошибок и компании приходится тратить дополнительные ресурсы на тестирование.
Длительные циклы разработки и развёртывания. При каждом изменении приходится тестировать всё приложение целиком. Это замедляет выпуск новых функций.
Трудно управлять командой. В больших командах работа над монолитом часто приводит к конфликтам и задержкам. Изменения, которые вносит одна команда, влияют на работу других команд.
Трудно масштабировать отдельные компоненты системы. Например, часть системы, которая отвечает за обработку заказов, испытывает высокую нагрузку. С монолитной архитектурой не получится масштабировать только эту часть — придётся масштабировать приложение целиком.
Эти проблемы особенно актуальны для приложений, если в них много легаси-кода. Или если их проектировали без учёта масштабирования и модульности. В таких системах внесение изменений становится всё более сложным и рискованным.
💡 Все эти факторы замедляют внедрение новых функций, усложняют обслуживание системы и увеличивают время выхода на рынок. Это тормозит развитие бизнеса.
Теперь разберём, как эти проблемы могут проявиться в конкретном проекте.
Сергей
Пример
Представьте крупную транспортную компанию CityTransit. Компания создала приложение, которое показывает расписание автобусов в мегаполисе. На начальном этапе компания использовала единую систему для управления расписанием и мониторингом транспорта. Монолитная архитектура закрывала все потребности бизнеса, пока компания не выиграла тендер от муниципалитета.
Согласно условиям тендера, приложение станет официальным источником информации о транспорте в городе. Ожидается, что число пользователей кратно увеличится. А разработчикам нужно будет добавить:
новые виды транспорта — трамваи и метро,
новую функцию — билет на любой транспорт можно купить через мобильное приложение.
На этом этапе монолит начал создавать проблемы:
Высокий риск ошибок. Обновление расписания автобусов в монолитной архитектуре может непредсказуемо повлиять на расписания трамваев и метро из-за общей кодовой базы. Это увеличивает риск ошибок и требует дополнительных ресурсов на тестирование и отладку всей системы.
Длительные циклы разработки и развёртывания. Есть риск, что CityTransit не успеет выполнить условия тендера к назначенным срокам. Компании нужно ускорить разработку новых функций.
Трудно управлять командой. Сейчас все компоненты приложения объединены в единый блок. Чтобы внести какое-то изменение или добавить функциональность, нужно внести изменения во всё приложение. Задачи, которыми занимаются разные команды, могут блокировать друг друга.
Трудно масштабировать отдельные компоненты системы. Объёмы данных о пассажирах и транспорте возрастут, но масштабировать систему уже на этом этапе практически невозможно.
В таких условиях традиционная монолитная архитектура начала тормозить развитие компании. Работать будет проще, если разбить приложение на несколько микросервисов:
Расписание транспорта — микросервис отвечает за расписание всех видов транспорта.
Мониторинг транспорта — микросервис отслеживает местоположение транспортных средств и предоставляет данные о задержках и пробках.
В новой архитектуре над каждой бизнес-функцией будет работать отдельная команда. Это ускорит разработку и поможет избежать ошибок.
Микросервисы VS модульный монолит
Распиливание монолита на микросервисы — это далеко не универсальное решение. Оно приносит плоды только на определённом уровне сложности и требует взамен немало ресурсов.
Микросервисы хорошо себя показывают в больших и сложных проектах. Например, в Netflix сейчас сотни микросервисов. Один сервис отвечает за показ видео, другой — за рекомендации фильмов, третий — за обработку платежей и так далее. Это позволяет Netflix быстро добавлять новые функции и улучшать существующие без риска сломать всю систему. Микросервисную архитектуру также используют Amazon и Spotify. У каждого из этих сервисов больше 200 миллионов только платных подписчиков.
Если ваш проект пока не настолько крупный и сложный, а монолит уже начинает доставлять неудобства, вы можете рассмотреть другой вариант архитектуры — модульный монолит.
✏️ Модульный монолит организует базу кода в чётко определённые модули в рамках одного приложения. Эти модули обычно организованы вокруг бизнес-функций или принципов предметно-ориентированного проектирования.
Вот сводная таблица, где собраны ключевые параметры всех трёх архитектурных стилей:
Чтобы принять взвешенное решение о внедрении микросервисов, нужно хорошо понимать плюсы и минусы этого архитектурного стиля. Сосредоточимся на них.
Плюсы микросервисов
1. Независимость компонентов
Микросервисы представляют собой отдельные блоки, которые можно разрабатывать, тестировать, развёртывать и масштабировать независимо друг от друга. Команды работают над своими задачами параллельно, не мешая друг другу. Это позволяет быстро внедрять изменения.
Пример. В компании CityTransit микросервис, который отвечает за продажу билетов, можно обновить или масштабировать независимо. Не придётся останавливать работу микросервиса, который занимается расписанием транспорта, или вносить в него изменения.
2. Модульность
Микросервисная архитектура разбивает приложение на небольшие модули, каждый из которых отвечает за конкретную бизнес-функцию. Это упрощает понимание кода, управление им и его повторное использование.
Пример. Предположим, что в CityTransit есть микросервис для управления пользователями. Его можно использовать как в системе продажи билетов, так и в системе мониторинга транспорта.
3. Легковесные коммуникации
Микросервисы общаются друг с другом через легковесные протоколы — HTTP/HTTPS, REST или сообщения в очередях. Это минимизирует накладные расходы и упрощает интеграцию сервисов.
Пример. Микросервис для мониторинга транспорта в CityTransit может отправлять данные о задержках и пробках другим микросервисам через HTTP API.
4. Автономность
Каждый микросервис работает в своём собственном процессе и может быть развёрнут независимо от других. Это снижает риски сбоев и повышает гибкость системы.
Пример. Если в CityTransit выйдет из строя микросервис для обработки платежей, остальные микросервисы продолжат работать без сбоев.
5. Устойчивость к отказам
Отказ одного микросервиса не приводит к отказу всей системы. Это делает систему более надёжной и устойчивой к ошибкам.
Пример. Если в CityTransit упадёт микросервис для продажи билетов, пользователи всё равно смогут просматривать расписание транспорта и отслеживать его местоположение.
6. Масштабируемость
Микросервисы можно масштабировать независимо. Это позволяет эффективно использовать ресурсы и справляться с увеличивающейся нагрузкой.
Пример. Если количество запросов на систему мониторинга транспорта в CityTransit увеличится, этот микросервис можно будет масштабировать отдельно, не затрагивая другие части системы.
7. Ориентация на бизнес
Каждый микросервис ориентирован на конкретную бизнес-функцию и разрабатывается вокруг неё. Это упрощает управление системой и её развитие в соответствии с бизнес-требованиями.
Пример. Микросервис для управления скидками в CityTransit разработают с учётом специфики бизнес-процессов, которые связаны со скидками и акциями в этой компании.
Хотя у такой архитектуры много плюсов, у неё также есть и недостатки. Рассмотрим основные вызовы, с которыми команды сталкиваются при использовании микросервисов.
Минусы микросервисов
1. Более сложное управление
Микросервисная архитектура усложняет управление, потому что приходится отслеживать и поддерживать множество независимых сервисов. Управление несколькими сервисами требует более сложной инфраструктуры. Возникает необходимость в специализированных инструментах для мониторинга и логирования.
Пример. В CityTransit команда должна следить за работоспособностью каждого микросервиса, что требует дополнительных ресурсов и инструментов.
2. Более сложная разработка
При разработке микросервисов нужно продумывать, как микросервисы будут взаимодействовать друг с другом. Командам приходится тщательно проектировать интерфейсы и взаимодействия между сервисами, а ещё согласовывать между собой контракты API.
Пример. При разработке новых функций в CityTransit команды должны постоянно синхронизировать свои действия, чтобы интерфейсы микросервисов были совместимыми.
3. Распределённые системы
Микросервисы работают в распределённой среде, что усложняет отладку и тестирование. Проблемы сложнее диагностировать, потому что ошибки могут возникать в разных частях системы. В распределённой среде сложнее обеспечить согласованность данных и управлять транзакциями.
Пример. В CityTransit сбой в одном микросервисе может вызвать цепочку сбоев в других микросервисах. Из-за этого будет сложнее определить первопричину проблемы.
4. Сетевые задержки и надёжность
Микросервисы взаимодействуют друг с другом через сеть. Это может вызывать задержки и создавать дополнительные точки отказа. Сетевые задержки могут ухудшить производительность системы. Командам необходимо предусмотреть обработку ошибок сетевого взаимодействия и обеспечить надёжную коммуникацию.
Пример. В CityTransit задержка в передаче данных между микросервисами может замедлить обновление расписания или обработку билетов.
5. Более сложное управление конфигурацией
Управлять конфигурациями множества микросервисов — это сложный процесс. Чтобы избежать ошибок, нужно централизовать управление конфигурациями и секретами. Необходимо обеспечить согласованность конфигураций между разными окружениями — например, между общим продакшеном и тестовыми серверами разных микросервисов.
Пример. В CityTransit каждая команда будет управлять конфигурациями своих микросервисов, что может привести к ошибкам и несогласованности.
6. Повышенные требования к DevOps и инфраструктуре
Микросервисная архитектура требует более сложных DevOps-практик и инфраструктуры. Нужно автоматизировать развёртывания, мониторинг и управление микросервисами. Для этого нужны контейнеры и оркестраторы — например, Kubernetes.
Пример. Чтобы эффективно управлять жизненным циклом микросервисов, CityTransit нужно внедрить и поддерживать DevOps-процессы.
7. Повышение затрат
Разработка и поддержка микросервисной архитектуры выходит дороже, чем монолитной. Затраты на разработку, тестирование и развёртывание увеличиваются. Инструменты и инфраструктура для управления микросервисами требуют дополнительных расходов.
Пример. Если CityTransit в результате декомпозиции монолита создаст много микросервисов, компания столкнётся со значительным увеличением расходов на разработку и поддержку инфраструктуры.
Теперь перейдём к особенностям микросервисной архитектуры. Обсудим, как на неё влияет структура команд и через какие этапы компания проходит при работе с микросервисами.
Закон Конвея
Микросервисы — это во многом организационное решение. Архитектура влияет на структуру команд разработчиков. Но верно и обратное — структура команд влияет на архитектуру приложения.
В 1967 году Мелвин Конвей сформулировал закон, который гласит:
Любая организация, которая проектирует систему, неизбежно создаёт дизайн, который копирует структуру коммуникаций этой организации.
Это означает, что архитектура программного обеспечения отражает коммуникационные структуры внутри организации.
Представьте себе крупную компанию Pear Inc. Она состоит из нескольких команд: одна команда отвечает за разработку пользовательского интерфейса, другая — за серверную часть, третья — за базы данных, а четвёртая — за тестирование и контроль качества.
Согласно закону Конвея, структура системы, которую разработает Pear Inc, будет отражать эту организационную структуру. Команда, которая отвечает за серверную часть, создаст отдельный компонент. Он будет взаимодействовать с компонентом, который разработала команда баз данных. И так далее.
Сергей
Как закон Конвея влияет на микросервисную архитектуру?
Понимание этого закона помогает лучше структурировать взаимодействие между сервисами и организовать работу команд.
Разделение ответственности. В микросервисной архитектуре каждая команда отвечает за свой сервис. Это способствует чёткому разделению ответственности и повышает автономность команд.
Минимизация зависимостей. Команды могут работать независимо друг от друга, что минимизирует количество зависимостей между сервисами. Это позволяет каждой команде быстро вносить изменения в свой сервис без риска нарушить работу других частей системы.
Оптимизация коммуникаций. Микросервисная архитектура отражает коммуникационные пути внутри организации. Например, если две команды тесно сотрудничают, их микросервисы будут чаще взаимодействовать между собой. Это помогает оптимизировать и упростить внутренние процессы.
Вернёмся к транспортной компании CityTransit. Разработкой занимаются три команды: одна команда работает над расписанием транспорта, вторая — над продажей билетов, третья — над мониторингом транспорта.
Согласно закону Конвея, при переходе на микросервисную архитектуру компании стоит организовать архитектуру так:
Такая структура позволит каждой команде работать автономно и сосредоточиться на своих задачах. Это улучшит эффективность и скорость разработки.
Преимущества от разделения по закону Конвея
Повышенная автономность команд. Команды могут работать независимо, что снижает количество межкомандных взаимодействий и упрощает управление проектом.
Улучшенная гибкость и адаптивность. Каждая команда может быстро реагировать на изменения требований и вносить необходимые улучшения в свой микросервис без необходимости координироваться с другими командами.
Оптимизированная архитектура. Архитектура системы становится отражением эффективных коммуникационных путей внутри организации. Это улучшает общую производительность и согласованность.
Осталось обсудить ещё одну важную вещь — жизненный цикл микросервиса.
Жизненный цикл микросервиса
✏️ Жизненный цикл микросервиса — это этапы, которые микросервис проходит от первоначальной идеи до вывода из эксплуатации.
Если команда разработки не понимает, как устроен этот процесс, могут возникнуть такие проблемы:
Неоптимальная разработка и развёртывание. Без чёткого понимания всех этапов жизненного цикла команды столкнутся с задержками и ошибками на разных стадиях разработки и развёртывания микросервиса. Это замедлит выход на рынок и снизит конкурентоспособность продукта.
Проблемы с масштабированием. Недостаток знаний о жизненном цикле может привести к трудностям в масштабировании. В итоге система не сможет справиться с возросшим количеством пользователей или данных.
Низкая устойчивость к отказам. Неправильное управление микросервисами ведёт к частым сбоям и падениям системы. Это негативно отражается на пользовательском опыте и бизнес-процессах. В худшем сценарии компания может потерять клиентов и доходы.
Повышенные затраты на поддержку. Плохо организованный жизненный цикл приводит к увеличению затрат на поддержку и обслуживание микросервисов. Это происходит из-за того, что команды тратят много времени на исправление ошибок. В итоге операционные расходы растут, а общая эффективность снижается.
Итак, жизненный цикл микросервиса состоит из восьми этапов:
Рассмотрим каждый этап по порядку.
Этап 1. Проектирование
Работа над микросервисом начинается с определения его цели и функциональности. На этом этапе команда анализирует бизнес-требования и принимает решения о границах микросервиса.
Задачи:
Определить бизнес-функцию, которую будет выполнять микросервис.
Определить границы микросервиса и его взаимодействия с другими сервисами.
Выбрать технологии и инструменты для реализации микросервиса.
Этап 2. Разработка
На этом этапе команда разработчиков пишет, тестирует и документирует код, следуя принципам разработки микросервисов.
Задачи:
Написать исходный код микросервиса.
Протестировать код — выполнить юнит-тесты и интеграционные тесты.
Задокументировать API и внутреннюю логику микросервиса.
Этап 3. Тестирование
Тестирование микросервиса включает в себя проверку его функциональности, производительности и безопасности. Этот этап помогает выявить и устранить ошибки до того, как микросервис развёрнут в производственной среде.
Задачи:
Провести модульные тесты, чтобы проверить отдельные компоненты микросервиса.
Провести интеграционные тесты, чтобы проверить, как микросервис взаимодействует с другими микросервисами.
Провести нагрузочное тестирование, чтобы оценить производительность микросервиса.
Этап 4. Развёртывание
Развёртывание микросервиса включает в себя его установку и настройку в производственной среде. На этом этапе рекомендуется тщательно координировать действия команды и использовать инструменты автоматизации. Это позволит минимизировать риски и простои.
Задачи:
Подготовить среду для развёртывания — настроить серверы и контейнеры.
Автоматизировать процесс развёртывания с помощью CI/CD-инструментов.
Развернуть микросервис в производственной среде.
Этап 5. Мониторинг и поддержка
Когда микросервис уже развёрнут в продакшене, важно обеспечить его стабильную работу и оперативно реагировать на возникающие проблемы. Мониторинг и поддержка помогают выявить и устранить неполадки, а также оптимизировать производительность.
Задачи:
Настроить мониторинг, чтобы отслеживать состояние и производительность микросервиса.
Реагировать на инциденты и устранять неполадки.
Обновлять микросервис и внедрять улучшения на основе собранных данных.
Этап 6. Масштабирование
Чтобы микросервис справился с возрастающей нагрузкой, может потребоваться масштабирование. Для этого нужно увеличить ресурсы или развернуть дополнительные экземпляры микросервиса.
Задачи:
Проанализировать метрики и логи, чтобы выявить потребность в масштабировании.
Увеличить ресурсы (CPU, память) или количество экземпляров микросервиса.
Обеспечить балансировку нагрузки между экземплярами.
Этап 7. Обновление и улучшение
Чтобы микросервис оставался актуальным и соответствовал меняющимся бизнес-требованиям, нужно постоянно улучшать и обновлять его. На этом этапе команда добавляет новые функции, исправляет ошибки и оптимизирует производительность.
Задачи:
Собрать обратную связь от пользователей и проанализировать метрики, чтобы выявить области для улучшения.
Разработать и протестировать новые функции.
Обновить микросервис в производственной среде.
Этап 8. Вывод из эксплуатации
Если микросервис устарел или его функции стали ненужными, его выводят из эксплуатации. Чтобы избежать сбоев и потери данных, этот этап нужно тщательно спланировать.
Задачи:
Оповестить пользователей и другие команды о том, что вы планируете вывести микросервис из эксплуатации.
Если нужно, перенести данные и функции на другие сервисы.
Отключить микросервис и удалить его из производственной среды.
💡 Сохраните чек-лист. Тогда жизненный цикл микросервиса всегда будет под рукой.
Задание 5
Перед вами этапы жизненного цикла микросервиса обработки платежей, который разработали в CityTransit. Расположите их в правильном порядке.
Разработчики создали API для приёма и обработки платёжных запросов, а также интегрировали микросервис с разными платёжными системами
2 этап
Это этап разработки. Он второй в жизненном цикле.
Команда определила, что микросервис будет отвечать за обработку всех транзакций, связанных с покупкой билетов, и интеграцию с разными платёжными системами
1 этап
Это этап проектирования. Он первый в жизненном цикле.
Пользователи заметили ошибку в работе сервиса, команда заметила проблему и разбирается с ней
5 этап
Это этап мониторинга и поддержки. Он пятый в жизненном цикле.
Микросервис развернули в производственной среде
4 этап
Это этап развёртывания. Он четвёртый в жизненном цикле.
Теперь в общественном транспорте оплачивают проезд через сканирование лица. Микросервис больше не нужен, его выводят из эксплуатации
8 этап
Это этап вывода из эксплуатации. Он восьмой в жизненном цикле.
В новогодние праздники нагрузки на микросервис увеличились. Чтобы он работал стабильно, нужно провести масштабирование
6 этап
Это этап масштабирования. Он шестой в жизненном цикле.
Микросервис тщательно протестировали, чтобы выявить и устранить все ошибки
3 этап
Это этап тестирования. Он третий в жизненном цикле.
Если бизнес-требования к микросервису меняются, код дорабатывают и обновляют
7 этап
Это этап обновления и улучшения. Он седьмой в жизненном цикле.
Итоги
Концепция микросервисов появилась в начале 2000-х годов. Понятие предложил Питер Роджерс. Концепцию описали и популяризировали Мартин Фаулер и Джеймс Льюис.
Микросервисная архитектура помогает справиться с проблемами, которые появляются у больших и сложных монолитов. К ним относят высокий риск ошибок, длительные циклы разработки, трудности в управлении командой и масштабировании.
Если приложение уже не маленькое, но пока и не огромное, не стоит сразу внедрять микросервисы. Лучше сначала перейти к модульному монолиту.
Среди плюсов микросервисной архитектуры: независимость, модульность и автономность компонентов, легковесные коммуникации между ними, устойчивость системы к отказам, масштабируемость и ориентация на бизнес.
К недостаткам микросервисов относят: сложности с разработкой системы и её управлением, проблемы из-за распределённого характера системы, задержки из-за взаимодействия микросервисов по сети, более трудоёмкое управление конфигурацией, повышенные требования к DevOps и инфраструктуре, а также увеличение накладных расходов.
При проектировании микросервисов нужно помнить о законе Конвея. Согласно ему, структура команд и коммуникации между ними влияют на итоговый вид архитектуры приложения.
Чтобы избежать проблем при разработке микросервисов, команда должна знать, как устроен жизненный цикл микросервиса. Он состоит из восьми этапов: от проектирования до вывода из эксплуатации.
В следующем уроке погрузимся в Domain-Driven Design. Этот подход помогает спроектировать микросервисы с учётом потребностей бизнеса.