1. Введение и обзор
Данный материал основан на выпуске подкаста Software Engineering Radio (эпизод 213), в котором Йоханнес Тёнес и Джеймс Льюис обсуждают тему микросервисов. Беседа исследует определение, мотивацию и практические аспекты, связанные с этим архитектурным стилем, который набирал значительную популярность в начале 2015 года как ответ на вызовы поддержки крупных монолитных приложений.
2. Определение микросервисов
Микросервис концептуализируется как небольшой, сфокусированный компонент приложения.
2.1 Ключевые характеристики
Согласно обсуждению, микросервис обладает несколькими ключевыми атрибутами:
- Независимое развертывание: Может быть развернут без внесения изменений в другие сервисы.
- Независимое масштабирование: Может масштабироваться горизонтально или вертикально в зависимости от своей конкретной нагрузки.
- Независимое тестирование: Может быть проверен изолированно.
- Единая ответственность: Имеет одну основную причину для изменения или замены. Выполняет одну связную задачу и легко понимается.
2.2 Примеры единой ответственности
«Единая вещь», которую делает микросервис, может быть функциональной или кросс-функциональной (нефункциональной):
- Функциональная: Обслуживание конкретного ресурса предметной области (например, сервис Пользователей, сервис Статей, сервис расчета Рисков в страховании).
- Кросс-функциональная: Обработчик очереди, который читает сообщение, применяет бизнес-логику и передает его дальше. Ответственность за конкретное нефункциональное требование, такое как кэширование или логирование.
3. Возникновение микросервисов
3.1 Движущие силы популярности
Популярность микросервисов объясняется широко распространенной отраслевой проблемой: неуправляемым монолитным приложением. Организации сталкиваются с приложениями, которые развивались в течение 5-10 лет, становясь слишком сложными для модификации, развертывания как SaaS или эффективного масштабирования в облаке.
3.2 Решение проблемы технического долга
Микросервисы возникли как решение для разделения этих монолитов на меньшие, взаимодействующие компоненты, работающие вне процесса. Этот подход, продемонстрированный в масштабе такими компаниями, как Netflix, позволяет осуществлять независимое обслуживание, масштабирование и замену. Основной движущей силой является необходимость доставлять программное обеспечение быстрее и использовать такие практики, как непрерывная поставка, которым препятствуют монолитные архитектуры.
4. Паттерны внедрения и реализации
4.1 Greenfield vs. Brownfield
Ключевой вопрос заключается в том, начинать ли новый проект с микросервисов (greenfield) или рефакторить существующий монолит в них (brownfield). В обсуждении отмечается, что эмпирически большинство организаций начинают с монолита и позже проводят рефакторинг, сталкиваясь с задачей определения ограниченных контекстов и границ внутри существующей кодовой базы.
4.2 Операционная сложность
В отрывке подкаста упоминается, что ограничения по объему не позволили полностью обсудить операционную сложность и ее влияние на DevOps. Это подразумевает, что хотя микросервисы решают проблемы разработки и масштабируемости, они создают новые вызовы в мониторинге, оркестрации развертывания и надежности сети.
5. Ключевые выводы и анализ
Основной вывод
Микросервисы — это не серебряная пуля; это организационный и экономический ответ на узкое место монолитной разработки. Реальное ценностное предложение, на которое намекает пример Netflix, — это обеспечение независимых, параллельных потоков поставки ценности. Эта архитектура напрямую направлена на снижение затрат на координацию и трения при развертывании, которые преследуют большие команды, работающие над единой кодовой базой — проблема, формализованная афоризмом Мелвина Конвея о том, что «организации, проектирующие системы... вынуждены создавать проекты, которые являются копиями коммуникационных структур этих организаций». Микросервисы пытаются инвертировать это, проектируя системы, которые навязывают желаемые коммуникационные структуры.
Логическая последовательность
Повествование следует убедительной причинно-следственной цепочке: (1) Монолиты накапливают технический долг и становятся парализованными для изменений. (2) Бизнес требует облачной масштабируемости и непрерывной поставки. (3) Монолитная архитектура принципиально несовместима с этими целями из-за сильной связанности. (4) Решение — раздробить монолит по ограниченным контекстам, создав независимо развертываемые единицы. Эта логика верна, но упускает огромную промежуточную сложность — «как» осуществить это дробление.
Сильные и слабые стороны
Сильные стороны: Фокус на независимой развертываемости как главной характеристике абсолютно верен. Это тот рычаг, который открывает автономию команд и более быстрые циклы выпуска. Связь с Законом Конвея и CQRS (упомянутыми как опущенные темы) показывает осведомленность о более глубоких социотехнических паттернах.
Слабые стороны: Перспектива 2015 года заметно оптимистична в отношении легкости определения «единой ответственности». Последующий отраслевой опыт показал, что это самая сложная часть — проклятие плохо определенных границ сервисов, ведущее к распределенным монолитам. Расшифровка также опасно преуменьшает операционные накладные расходы. Как позже подробно описал знаковая статья Фаулера, вы обмениваете сложность разработки на сложность эксплуатации. Упоминание Docker как «популярного инструмента» — это исторический снимок; экосистема контейнеризации была недостающим операционным фактором, который сделал микросервисы практически жизнеспособными в масштабе.
Практические рекомендации
Для руководителей: Не начинайте с микросервисов, потому что это модно. Начните с измерения вашего времени выполнения изменений и частоты развертываний. Если они низкие из-за координации в кодовой базе, рассмотрите микросервисы. Для архитекторов: Основной инструмент проектирования — не контрольный список технологий, а карта контекстов предметно-ориентированного проектирования (DDD). Определяйте границы на основе бизнес-возможностей, а не технических слоев. Для команд: Инвестируйте в платформенную инженерию заранее — автоматизированное развертывание, обнаружение сервисов и наблюдаемость — это не второстепенные задачи; это фундамент. Предлагаемый путь — рефакторинг из монолита — по-прежнему самый мудрый. Используйте Паттерн «Фикус-душитель» (Strangler Fig Pattern) для постепенной замены частей монолита сервисами, так как это управляет рисками и позволяет учиться.
6. Техническая основа и математические модели
Хотя подкаст носит разговорный характер, лежащие в его основе принципы могут быть формализованы. Ключевой моделью является взаимосвязь между размером команды (N), путями коммуникации и архитектурной связанностью.
В монолитной архитектуре с N командами потенциальные пути коммуникации масштабируются как $O(N^2)$, поскольку изменения в одном модуле могут затрагивать многие другие. Это создает накладные расходы на координацию. Микросервисы стремятся уменьшить это, навязывая ограниченные контексты и API. Цель состоит в том, чтобы сделать стоимость межсервисной коммуникации, $C_{comm}$, явно высокой через сетевые вызовы, тем самым поощряя сильную модульность внутри сервиса, где стоимость изменения, $C_{internal}$, низка.
Упрощенная модель вероятности распространения изменений ($P_{prop}$) может быть:
$P_{prop} \approx \frac{C_{comm}}{C_{comm} + C_{internal}}$
Где хорошо спроектированная микросервисная архитектура минимизирует $P_{prop}$ для несвязанных изменений, делая $C_{comm}$ (сетевая задержка, версионирование API) доминирующим фактором для изменений, пересекающих границы.
7. Результаты экспериментов и кейсы
В подкасте в качестве основного кейса приводится Netflix. К 2015 году Netflix знаменито декомпозировал свой монолитный бэкенд на сотни микросервисов, что позволило:
- Независимое масштабирование: Сервисы, такие как рекомендации фильмов или биллинг, могли масштабироваться независимо во время пиковых нагрузок.
- Быстрая инновация: Команды могли развертывать свои сервисы несколько раз в день без координации со всей стопкой.
- Технологическая гетерогенность: Разные сервисы могли быть написаны на языке, наиболее подходящем для их задачи (например, Java, Node.js).
Описание диаграммы (гипотетическое): Столбчатая диаграмма, сравнивающая монолитное приложение с микросервисной архитектурой по двум осям: (1) Частота развертываний (Развертываний/день): Монолит показывает низкий столбец (например, 0.1), Микросервисы показывают высокий столбец (например, 50+). (2) Среднее время восстановления (MTTR) после сбоя: Монолит показывает высокий столбец (например, 4 часа), Микросервисы показывают более низкий столбец (например, 30 минут), так как сбои могут быть изолированы в конкретных сервисах.
Последующие исследования, такие как упомянутые в отчетах State of DevOps, статистически связали слабосвязанные, сервис-ориентированные архитектуры с более высокой производительностью поставки ПО.
8. Фреймворк анализа: практический пример
Сценарий: Монолитное e-commerce приложение испытывает трудности с обновлениями. Изменения в функции «оформления заказа» требуют полного регрессионного тестирования и конфликтуют с обновлениями «каталога товаров».
Применение фреймворка:
- Определение ограниченных контекстов: Используя предметно-ориентированное проектирование, определите основные домены: Оформление заказов, Каталог, Складские запасы, Управление пользователями, Оплата.
- Определение границ сервисов: Создайте микросервис для каждого контекста. Сервис Заказов владеет логикой оформления заказа и данными заказов.
- Установление контрактов: Определите четкие API. Сервис Заказов будет вызывать API Сервиса Оплаты
processPayment(orderId, amount)и API Сервиса Складских запасовreserveStock(itemId, quantity). - Владение данными: Каждый сервис владеет своей базой данных. Сервис Заказов имеет свою собственную таблицу «orders»; он не запрашивает напрямую базу данных Складских запасов.
- Развертывание и наблюдаемость: Каждый сервис контейнеризован, развертывается независимо и публикует метрики (задержка, частота ошибок) на центральную панель управления.
Результат: Команда, отвечающая за оформление заказа, теперь может развертывать обновления в Сервисе Заказов без участия команд каталога или склада, значительно снижая накладные расходы на координацию и увеличивая частоту развертываний.
9. Будущие применения и направления исследований
Эволюция микросервисов продолжается за пределами взглядов 2015 года:
- Сервисные сетки (Service Meshes): Появились такие технологии, как Istio и Linkerd, для обработки сквозных задач (безопасность, наблюдаемость, управление трафиком) на уровне инфраструктуры, снижая нагрузку на код отдельных сервисов.
- Бессерверные вычисления и FaaS: Функции как услуга (например, AWS Lambda) представляют собой крайнюю форму микросервисов, полностью перенося операционную сложность на облачного провайдера и обеспечивая еще более детальное масштабирование.
- Интеграция с ИИ/МО: Микросервисы становятся де-факто паттерном для развертывания ML-моделей в качестве независимых сервисов предсказания, позволяя проводить A/B-тестирование и быструю итерацию алгоритмов.
- Периферийные вычисления (Edge Computing): Развертывание легковесных микросервисов на периферийных устройствах для обработки с низкой задержкой в сценариях IoT и аналитики в реальном времени.
- Фокус исследований: Будущие исследования необходимы в области инструментов автоматической декомпозиции сервисов, интеллектуального прогнозирования сбоев в распределенных системах и формальной верификации взаимодействий в сервисных хореографиях.
10. Ссылки
- Lewis, J., & Fowler, M. (2014). Microservices. MartinFowler.com. Retrieved from https://martinfowler.com/articles/microservices.html
- Newman, S. (2015). Building Microservices. O'Reilly Media.
- Forsgren, N., Humble, J., & Kim, G. (2018). Accelerate: The Science of Lean Software and DevOps. IT Revolution Press.
- Conway, M. E. (1968). How Do Committees Invent? Datamation, 14(5), 28-31.
- Google Cloud. (2019). The 2019 Accelerate State of DevOps Report. DORA.
- Netflix Technology Blog. (Various). https://netflixtechblog.com/