![](https://habrastorage.org/files/b77/3ef/843/b773ef843dc249509d033e609f4d5a44.jpg)
К сожалению, у меня нет опыта работы с микросервисами, но около года назад я очень активно интересовался этой темой и изучил все источники информации, какие смог найти. Я просмотрел несколько выступлений на конференциях, прочитал несколько статей очень авторитетных и опытных специалистов вроде Мартина Фаулера, Фреда Джорджа, Эдриана Кокрофта и Криса Ричардсона, чтобы как можно больше узнать о микросервисах. Эта статья — результат моих изысканий.
Содержание
- SOA и микросервисы
- Когда следует использовать микросервисы?
- Предпосылки
- Характеристики
- Что такое микросервис?
- Насколько велик микросервис?
- Компонентное представление через сервисы
- Гетерогенность
- Организация человеческих ресурсов в соответствии с возможностями бизнеса
- Продукты, а не проекты
- Умные конечные точки и глупые каналы (Smart endpoints and dumb pipes)
- Децентрализованное управление
- Децентрализованное управление данными
- Автоматизация инфраструктуры
- Страховка от сбоев (Design for failure)
- Эволюционная архитектура
- Фронтенд/бэкенд
- Опасности
- Как декомпозировать единое приложение
- Заключение
Микросервисная архитектура — это подход к созданию приложения, подразумевающий отказ от единой, монолитной структуры. То есть вместо того чтобы исполнять все ограниченные контексты приложения на сервере с помощью внутрипроцессных взаимодействий, мы используем несколько небольших приложений, каждое из которых соответствует какому-то ограниченному контексту. Причём эти приложения работают на разных серверах и взаимодействуют друг с другом по сети, например посредством HTTP.
Иными словами, мы инкапсулируем определённые контексты приложения в микросервисы, по одному на каждый, а сами микросервисы крутим на разных серверах.
SOA и микросервисы
Согласно Мартину Фаулеру, термином SOA злоупотребляют все кому не лень, сегодня под ним подразумевают множество вещей. С точки зрения Мартина, микросервисы — это разновидность SOA.
Когда следует использовать микросервисы?
Как архитектор-теоретик, желающий стать практиком, я считаю следующее. Решая, использовать ли микросервисы, ни в коем случае нельзя руководствоваться мифами, или желанием «в следующий раз попробовать это», или стремлением быть на переднем крае технологий. К этому, в соответствии с выводами Рейчел Майерс, нужно подходить исключительно с прагматической точки зрения. Рейчел отмечает, что архитектура должна:
- делать продукт гибче и устойчивее к сбоям;
- облегчать понимание, отладку и изменение кода;
- помогать в командной работе.
Я согласен с Рейчел, но я также считаю, что этим критериям удовлетворяют и монолитные архитектурные схемы.
Мартин Фаулер выделяет несколько преимуществ монолитной и микросервисной архитектур, что поможет вам решить, какой подход выбрать:
Преимущества | |
Монолитная архитектура | Микросервисы |
Простота Монолитная архитектура гораздо проще в реализации, управлении и развёртывании. Микросервисы требуют тщательного управления, поскольку они развёртываются на разных серверах и используют API. |
Частичное развёртывание Микросервисы позволяют по мере необходимости обновлять приложение по частям. При единой архитектуре нам приходится заново развёртывать приложение целиком, что влечёт за собой куда больше рисков. |
Согласованность (Consistency) При монолитной архитектуре проще поддерживать согласованность кода, обрабатывать ошибки и т. д. Зато микросервисы могут полностью управляться разными командами с соблюдением разных стандартов. |
Доступность У микросервисов доступность выше: даже если один из них сбоит, это не приводит к сбою всего приложения. |
Межмодульный рефакторинг Единая архитектура облегчает работу в ситуациях, когда несколько модулей должны взаимодействовать между собой или когда мы хотим переместить классы из одного модуля в другой. В случае с микросервисами мы должны очень чётко определять границы модулей! |
Сохранение модульности Сохранять модульность и инкапсуляцию может быть непросто, несмотря на правила SOLID. Однако микросервисы позволяют гарантировать отсутствие общих состояний (shared state) между модулями. |
Мультиплатформенность/гетерогенность Микросервисы позволяют использовать разные технологии и языки, в соответствии с вашими задачами. |
Лично мне нравится прагматичный подход Эрика Эванса. Микросервисы с точки зрения аппаратных ресурсов имеют преимущества, которых лишены единые архитектуры, а также облегчают решение ряда задач с программной точки зрения:
Микросервисы | |
Аппаратные преимущества | Программные преимущества |
Независимая масштабируемость При размещении модулей на отдельных серверных узлах мы можем масштабировать их независимо от других модулей. |
Сохранение модульности И единая, и микросервисная архитектуры позволяют сохранять модульность и инкапсуляцию. Однако это может быть довольно трудной задачей, на решение которой уйдут десятилетия, несмотря на правила SOLID. Зато микросервисы позволяют обеспечивать логическое разделение приложения на модули за счёт явного физического разделения по серверам. Физическая изолированность защищает от нарушения пределов ограниченных контекстов. |
Независимый технический стек Благодаря распределению модулей по разным серверным узлам и независимому языку взаимодействия мы можем использовать совершенно разные языки программирования, инструменты взаимодействия, мониторинга и хранения данных. Это позволяет выбирать лучшие и наиболее удобные решения, а также экспериментировать с новыми технологиями. |
Независимая эволюция подсистем Микросервис может развиваться и ломать обратную совместимость, не обременяя себя поддержкой старых версий, так как всегда можно оставить старую версию микросервиса работающей необходимое время. |
Я считаю, что основные причины для использования микросервисов — аппаратные преимущества, недостижимые с помощью единой архитектуры. Так что если вам важны вышеописанные моменты, то микросервисы безальтернативны. Если же аппаратные преимущества для вас некритичны, то сложность микросервисной архитектуры может перевесить её достоинства. Также мне кажется, что с помощью единой архитектуры невозможно достичь частичного развёртывания и частичной доступности, характерных для микросервисов. Это не ключевые преимущества (хотя это в любом случае преимущества).
Вне зависимости от наших вкусов и пожеланий НЕЛЬЗЯ начинать новый проект сразу с использованием микросервисной архитектуры. Вначале нужно сосредоточиться на понимании задачи и на способе её достижения, не тратя ресурсы на преодоление огромной сложности создания экосистемы микросервисов (Ребекка Парсонс, Саймон Браун).
Предпосылки
Непрерывное развёртывание
Возможность и нацеленность на постоянное ускорение работы
Одна из причин использования микросервисов заключается в том, что мы хотим иметь возможность быстро что-то менять, чтобы реагировать на изменения бизнес-требований, опережать конкурентов. Или, выражаясь словами Эрика Эванса, нам нужно осознавать хаос в компаниях:
Реальность разработки ПО такова, что вначале мы никогда не имеем полного понимания задачи. Наше понимание углубляется по мере работ, и нам постоянно приходится рефакторить. Так что рефакторинг — это потребность, но в то же время и опасность, потому что код становится запутанней, особенно при несоблюдении ограниченности контекстов. Микросервисы заставляют соблюдать пределы ограниченных контекстов, что позволяет сохранять работоспособность, ясность, изолированность и инкапсулированность кода в отдельных связных модулях. Если модуль/микросервис становится запутанным, то эта запутанность только в нём и остаётся, а не распространяется за его пределы.
Нам нужно действовать быстрее на всех стадиях разработки! Это верно для любой архитектуры, но микросервисы в этом отношении удобнее. Мартин Фаулер говорит, что необходимо иметь возможность:
- Быстро вводить в эксплуатацию: быстро развёртывать новые машины для разработки, тестирования, приёмки и работы.
- Быстро развёртывать приложения: автоматически и быстро развёртывать наши сервисы.
Фред Джордж утверждает то же самое: есть огромная потребность ускорить работу, чтобы выдержать конкуренцию! Он приводит ретроспективный анализ времени, необходимого на введение в эксплуатацию сервера, и отмечает, что в 1990-х требовалось 6 месяцев, в 2010-м благодаря облачным сервисам — 30 минут, а в 2015-м Docker позволял поднять и запустить новый сервер менее чем за минуту.
Эдриан Кокрофт, один из ключевых специалистов в Netflix Cloud и пионер в освоении микросервисов, отмечает, как важно находиться в первых рядах при освоении новых технологий, а также очень быстро вводить новые серверы и развёртывать новые версии своих приложений. Эдриан — большой поклонник Docker, поскольку этот сервис позволяет за секунды создавать сервер и развёртывать среды для разработки, тестирования и работы.
![image](https://habrastorage.org/getpro/habr/post_images/84a/680/977/84a68097797286651c2317b3cd869fe6.jpg)
Усложнившийся мониторинг
Мониторинг крайне важен (Ребекка Парсонс), нам необходимо сразу узнавать о том, что сервер упал, что какой-то компонент перестал отвечать, что происходят сбои вызовов, причём по каждому из микросервисов (Фред Джордж). Также нам нужны инструменты для быстрой отладки (Мартин Фаулер).
Сильная devops-культура
Нам нужны devops’ы для мониторинга и управления, при этом между ними и разработчиками должны быть тесные отношения и хорошее взаимодействие (Мартин Фаулер). При работе с микросервисами нам приходится больше развёртывать, усложняется система мониторинга, сильно разрастается количество возможных сбоев. Поэтому в компании очень важна сильная devops-культура (Ребекка Парсонс).
Характеристики
Мартин Фаулер и Джеймс Льюис в своей широко известной статье и выступлениях (Фаулер, Льюис) приводят набор характеристик для определения микросервиса.
Что такое микросервис?
Лично я полностью согласен с определением Эдриана Кокрофта:
Архитектура на основе свободно сопряжённых сервисов с ограниченными контекстами. (Loosely coupled service oriented architecture with bounded contexts.)
![image](https://habrastorage.org/getpro/habr/post_images/198/fff/a95/198fffa95356e666e896b65ada4af1e9.jpg)
Ограниченный контекст — это понятие явных границ вокруг какого-то бизнес-контекста. Например, в рамках электронной коммерции мы оперируем понятиями «темы» (themes), «поставщики платёжных услуг» (payment providers), «заказы», «отгрузка», «магазин приложений». Всё это ограниченные контексты, а значит — кандидаты в микросервисы.
Полезная общая информация о микросервисах приводится в книге Сэма Ньюмена «Building Microservices». По мнению Джеймса Льюиса, микросервисы должны:
- дёшево заменяться;
- быстро масштабироваться;
- быть устойчивыми к сбоям;
- никоим образом не замедлять нашу работу.
Насколько велик микросервис?
Джеймс Льюис утверждает, что сервис должен быть «настолько большим, чтобы умещаться в руке», то есть чтобы один человек мог полностью разобраться в его устройстве и работе.
Есть разные мнения о размерах микросервисов. Мартин Фаулер описывает случаи, когда соотношение количества сотрудников и сервисов колебалось от 60 к 20 до 4 к 200. К примеру, в Amazon используется подход с «командами на две пиццы» (two pizzas team): в команде микросервиса должно быть столько людей, чтобы их можно было накормить двумя пиццами.
Фред Джордж полагает, что микросервис должен быть «очень-очень маленьким», чтобы его создавал и сопровождал только один разработчик. То же самое говорит и Джеймс Льюис.
Я согласен с Джеймсом Льюисом, Фредом Джорджем и Эдрианом Кокрофтом. Мне кажется, микросервис должен соответствовать ограниченному контексту, который способен полностью понять один человек. То есть чем шире функциональность приложения, тем больше должно быть микросервисов. Например, в Netflix их около 800! (Фред Джордж)
Тем не менее как в самом начале жизненного цикла микросервиса, так и позднее ограниченный контекст может оказаться слишком велик для понимания одним человеком. Нужно выявлять такие ситуации и дробить подобные сервисы на более мелкие. Это соответствует концепциям архитектуры с эволюционным развитием и DDD, подразумевающим, что архитектура постоянно меняется/рефакторится по мере углубления в задачу и/или изменений бизнес-требований. Как говорит Ребекка Парсонс, «дробление крайне важно»: при разработке микросервисов труднее всего определять их границы. И при продвижении работы мы однозначно будем объединять или дробить сервисы.
Компонентное представление через сервисы
- Компонент — это элемент системы, который можно независимо заменить, усовершенствовать (Мартин Фаулер) и масштабировать (Ребекка Парсонс).
- При разработке ПО мы используем два типа компонентов:
А. Библиотеки: куски кода, применяемые в приложениях, которые могут дополняться или заменяться другими библиотеками, желательно без воздействия на остальную часть приложения. Взаимодействие происходит через языковые конструкты. Однако если интересующая нас библиотека написана на другом языке, мы не можем использовать этот компонент.
Б. Сервисы: части приложений, по факту представляющие собой маленькие приложения, выполняющиеся в собственных процессах. Взаимодействие выполняется за счёт межпроцессной связи, вызовов веб-сервисов, очереди сообщений и т. д. Мы можем использовать сервис, написанный на другом языке, поскольку он выполняется в собственном процессе (этот подход предпочитает Чед Фаулер). - Независимая масштабируемость — каждый сервис может быть масштабирован независимо от остального приложения.
Гетерогенность
Гетерогенность — это возможность построить систему с использованием разных языков программирования. У подхода есть ряд преимуществ (Мартин Фаулер), а Чед Фаулер считает, что системы обязаны быть гетерогенны по умолчанию, то есть разработчики должны стараться применять новые технологии.
Преимущества гетерогенной системы:
- Предотвращает возникновение тесных связей благодаря использованию разных языков.
- Разработчики могут экспериментировать с технологиями, что повышает их собственную ценность и позволяет не уходить в другие компании, чтобы попробовать новинки.
Правило. При экспериментах с новыми технологиями:
— нужно использовать маленькие элементы кода (code unit), модули/микросервисы, чтобы снизить риск;
— элементы кода должны быть одноразовыми (disposable).
Организация человеческих ресурсов в соответствии с возможностями бизнеса
Когда-то внутри команд разработчиков самоорганизовывались группы на основе используемых технологий. В результате проект создавали команда по DBA, команда разработки серверной части и команда разработки интерфейса, действовавшие независимо друг от друга. Такая схема сказывается на качестве продукта, потому что знания в конкретных областях и усилия по разработке рассеиваются по подгруппам.
При микросервисном подходе команды должны организовываться на основе бизнес-возможностей: например команда заказов, отгрузки, каталога и т. д. В каждой команде должны быть специалисты по всем необходимым технологиям (интерфейс, серверная часть, DBA, QA...). Это даст каждой команде достаточный объём знаний, чтобы сосредоточиться на создании конкретных частей приложения — микросервисов (Мартин Фаулер, Эрик Эванс).
Подход сочетается с законом Конвея, который гласит, что если нам нужны высокосвязные раздельные микросервисы, то структура организации должна отражать желаемую компонентную структуру.
Организации, разрабатывающие системы… создают архитектуры, которые копируют структуры взаимодействий внутри этих организаций.
Мелвин Конвей, 1967
Продукты, а не проекты
Раньше был такой подход: команда создаёт какую-то функциональность, а затем передаёт её на сопровождение другой команде.
В случае с микросервисами команда должна отвечать за свой продукт в течение всего его жизненного цикла, включая разработку, сопровождение и вывод из эксплуатации. Это формирует «продуктовое мышление», что означает сильную связь между техническим продуктом и его бизнес-возможностями. То есть создаётся прямая взаимосвязь: как приложение помогает своим пользователям расширить их бизнес-возможности.
Умные эндпойнты и глупые каналы (Smart endpoints and dumb pipes)
Опять же, в старые добрые времена компании использовали архитектуру Enterprise Service Bus (сервисная шина), при которой формируется канал коммуникаций между эндпойнтами и бизнес-логикой. Затем этот подход преобразился в spaghetti box.
Микросервисная архитектура переносит бизнес-логику в конечные точки и использует простые способы взаимодействия вроде HTTP.
Децентрализованное управление
Ключевые решения по микросервисам должны принимать люди, которые действительно разрабатывают микросервисы. Здесь под ключевыми решениями подразумевается выбор языков программирования, методологии развёртывания, контрактов публичных интерфейсов и т. д.
Децентрализованное управление данными
При традиционном подходе у приложения лишь одна база данных, и много разных компонентов бизнес-логики приложения «взаимодействуют» в рамках этой БД: напрямую читают из неё данные, принадлежащие другим компонентам. Это также означает, что для всех компонентов характерна одна и та же степень сохранности данных, даже если для каких-то из них это не самая лучшая ситуация (Мартин Фаулер).
При микросервисной архитектуре, когда каждый бизнес-компонент представляет собой микросервис, все компоненты обладают собственными базами данных, которые недоступны другим микросервисам. Данные компонента доступны (для чтения и записи) только через соответствующий интерфейс компонентов. Благодаря этому степень устойчивости данных варьируется в зависимости от компонента (Мартин Фаулер, Чед Фаулер).
С точки зрения Фреда Джорджа, это первый вызов на пути к микросервисной архитектуре.
![image](https://habrastorage.org/getpro/habr/post_images/66a/b64/157/66ab64157eae4346eded1d835853459c.jpg)
Автоматизация инфраструктуры
Непрерывное развёртывание (Мартин Фаулер, Ребекка Парсонс, Чед Фаулер, Эрик Эванс):
- «Голубое» и «зелёное» развёртывание: нулевое время простоя.
- Автоматизация: нажатием одной кнопки можно развернуть несколько серверов.
- Серверы Phoenix: быстрый запуск и остановка.
- Мониторинг: можно заметить, когда что-то пошло не так, и отладить.
Страховка от сбоев (Design for failure)
Серверы, по которым распределено приложение, рано или поздно падают, особенно разные узлы. Поэтому архитектура приложений должна быть устойчива к таким сбоям (Мартин Фаулер).
Chaos monkey — это инструмент, созданный в Netflix. Он позволяет выключать серверы для проверки устойчивости системы к такому типу отказов (Мартин Фаулер).
Ребекка Парсонс считает очень важным, что мы больше не используем даже внутрипроцессное взаимодействие между сервисами, вместо этого для связи мы прибегаем к HTTP, который и близко не бывает столь же надёжен. В результате будут возникать сбои при общении сервисов друг с другом, и система должна быть к этому готова.
Архитектура с эволюционным развитием
Архитектура всего приложения не должна быть статичной, необходима возможность её простого развития в соответствии с потребностями бизнеса. Например, можно:
- Превратить (рефакторить) единое приложение в приложение микросервисное, изолировав и перенеся наборы бизнес-логики (ограниченные контексты) в отдельные микросервисы.
- Объединить существующие микросервисы, например когда часто приходится одновременно изменять разные микросервисы.
- Разделить существующие микросервисы, когда нужно и есть возможность развивать их по отдельности или когда мы понимаем, что разделение серьёзно повлияет на бизнес-логику.
- Временно добавить в приложение какую-то возможность, создав микросервис, который будет работать определённое время.
Фронтенд/бэкенд
Есть два подхода к структурированию фронтенда и бэкенда при микросервисной архитектуре:
- Раскидать все части пользовательского интерфейса по микросервисам и сохранять взаимосвязи между соответствующими микросервисами. Это позволяет наладить внутрипроцессное взаимодействие между фронтендом и бэкендом. Но тогда будет очень сложно, если вообще возможно, поддерживать связность UI. В случае перекрёстных изменений границ в UI нам придётся одновременно обновлять несколько микросервисов, создавая взаимосвязи и нарушая изолированность и независимость микросервисов, обеспечиваемые самой архитектурой. Получается практически антипаттерн!
- Раскидать кодовые базы фронтенда и бэкенда, оставив UI приложения одним целым, чтобы они потом взаимодействовали по HTTP. Микросервисы будут отделены друг от друга, что дополнительно разделит фронтенд и бэкенд. Зато UI можно поддерживать целиком, легко сохраняя его связность. Такую структуру рекомендует использовать Рейчел Майерс, и, насколько я понимаю, это единственный способ. В таком случае у нас есть два варианта взаимодействия между фронтендом и бэкендом:
- Много маленьких асинхронных HTTP-запросов вместо одного большого, что исключит возможность блокировки (этот подход предпочитает Чед Фаулер).
- Один большой запрос к специализированным сервисам (шлюзу/агрегатору/кешу), которые собирают данные со всей микросервисной экосистемы. Это уменьшает сложность UI.
Опасности
Нужно управлять гибкостью технологии
Одно из преимуществ микросервисов заключается в том, что мы можем применять разные технологии для решения одной и той же задачи. Например, в каждом микросервисе использовать разные библиотеки для XML-парсинга или разные инструменты сохранности данных. Но сама возможность не означает, что мы должны это делать. Не исключено, что обилие технологий и библиотек выйдет из-под контроля. Так что выберите базовый набор инструментов и обращайтесь к другим только тогда, когда это действительно нужно (Ребекка Парсонс).
Нужно управлять нестабильностью интерфейса
В начале разработки микросервиса его API особенно нестабилен. Но даже на более поздних стадиях, когда микросервис достаточно отработан, нам приходится менять API, его ввод и вывод. Осторожно вносите изменения, потому что другие приложения будут полагаться на стабильность API (Ребекка Парсонс).
Необходимо быть уверенными в согласованности данных
Микросервисы имеют собственные хранилища данных. И во многих случаях данные, принадлежащие одному микросервису, будут частично или целиком скопированы другим, клиентским микросервисом. Когда данные у поставщика меняются, он инициирует событие для запуска обновления данных, скопированных клиентским микросервисом. Событие попадает в очередь сообщений и ожидает, когда его получит клиентский микросервис.
Эта схема означает, что клиентский микросервис будет обладать устаревшими данными, пока не обнаружит нужное событие. Данные не согласованы.
Конечно, в итоге изменения будут применены ко всем копиям, а данные снова станут согласованными. Это называется eventual consistency — согласованность в конечном счёте. То есть мы знаем, что в течение короткого периода времени данные остаются несогласованными. Этот эффект имеет важное значение в ходе разработки приложений, от серверной части до UX-уровней (Ребекка Парсонс).
Как декомпозировать единое приложение
Приступая к созданию приложения, нужно изначально придерживаться единой архитектуры — по причине её простоты. В то же время нужно стараться создавать его как можно более модульным, чтобы каждый компонент легко переносился в отдельный микросервис (Ребекка Парсонс). Это сочетается с идеей Саймона Брауна о разработке приложения в виде набора раздельных компонентов в едином развёртываемом модуле.
При декомпозиции единой архитектуры в микросервисную, или в набор раздельных компонентов, необходимо думать о нескольких измерениях в поддержку нашего решения:
- Думайте об ограниченных контекстах, как это определено в DDD (Ребекка Парсонс, Рейчел Майерс)
- Каждый микросервис должен представлять собой ограниченный контекст, с точки зрения концепции бизнеса и с технической точки зрения. Обычно в рамках микросервиса должны быть соединения между элементами кода (между данными и/или бизнес-логикой), а также несколько соединений с внешними элементами кода.
- Думайте о бизнес-возможностях (Ребекка Парсонс: 1, 2)
- Какие потоки создания ценностей (value streams) существуют в организации? Бизнес-продукты? Какие доставляются бизнес-сервисы?
- Думайте о нуждах потребителей (Ребекка Парсонс: 1, 2, 3)
- Мы можем посмотреть на продукт не только как создатели, но и как потребители: что они хотят от нашего сервиса? Как они будут его использовать? Чего они ожидают?
- Думайте о шаблонах взаимодействия
- Какие части системы могут использовать одни и те же данные? Какие бизнес-логики будут взаимодействовать интенсивнее? (Ребекка Парсонс: 1, 2, 3)
- Есть ли в архитектуре единая точка отказа благодаря жёсткой зависимости одного микросервиса от многих других? (Рейчел Майерс)
- Думайте об архитектуре данных (Ребекка Парсонс: 1, 2, 3, Рейчел Майерс)
- Сервисы обладают собственными данными, у них свои базы данных, и нам нужно исходить из принципа согласованности в конечном счёте. Если две структуры данных очень сильно зависят друг от друга, то может быть целесообразнее держать их в одном микросервисе, чтобы не пришлось создавать механизм для работы с согласованностью в конечном счёте.
- Думайте о шаблонах взаимосвязанных изменений (Ребекка Парсонс: 1, 2, 3, Рейчел Майерс)
- Если можно предвидеть одновременное изменение двух элементов кода, то лучше хранить их в одном микросервисе, чтобы исключить лишние усилия по изменению API.
- Будьте готовы к слиянию и разделению сервисов (Ребекка Парсонс)
- Вероятно, вы не сможете всегда делать это вовремя. Но по мере получения опыта и углубления в задачу мы начинаем лучше понимать расположение ограниченных контекстов. Бизнес тоже будет меняться, и нам придётся к этому быстро приспосабливаться! Так что наша система должна позволять быстро разделять и объединять микросервисы.
- Шаблон Tolerant reader (Ребекка Парсонс)
- Всегда может возникнуть необходимость внести критическое изменение в обратную совместимость (backwards compatibility breaking change). Но мы можем постараться делать это лишь в крайнем случае. Чтобы не менять свой сервис постоянно, создайте его так, чтобы сервис приходилось менять только при изменении действительно важных данных.
- Без сохранения состояния и узлы Phoenix (Рейчел Майерс, Чед Фаулер, Эрик Эванс)
- Не дублируйте статичные файлы (HTML, CSS, JS, изображения) в приложениях и сервисах.
- Приложения с пользовательским интерфейсом должны быть полностью отделены от микросервисной экосистемы.
- Используйте однократные узлы.
- Используйте неизменяемое развёртывание (immutable deployments): никогда не обновляйте ПО на существующих узлах.
- Приоритет соглашения над конфигурацией (Convention over configuration) (Чед Фаулер)
- Принятые в вашей архитектуре структура и система наименований должны быть одинаковыми для всей экосистемы микросервисов.
- Создайте генератор микросервисной песочницы, чтобы у вас была начальная точка с уже заданной привычной структурой.
- Оптимизация взаимодействия между микросервисами (Чед Фаулер)
- Создайте базовую клиентскую библиотеку HTTP REST, оптимизированную для REST-вызовов, на основе которой можно строить конкретный микросервисный клиент, им будут пользоваться другие микросервисы. Этот оптимизированный клиент должен быть портирован на все языки, применяемые в вашей экосистеме.
- Обнаружение сервисов (Service discovery) (Чед Фаулер)
- Каждый микросервис должен знать, как контактировать с другими. Можно использовать локализованный (для каждого сервиса) конфиг, обновляемый сразу во всех местах при изменении расположения микросервиса.
- Мониторинг (Чед Фаулер)
- Измеряйте всё: сеть, машины, приложение.
- При создании нового микросервиса необходимо оснащать его всей необходимой функциональностью по мониторингу.
- Миграция от единой архитектуры к микросервисам (Чед Фаулер)
- Лучше использовать много маленьких запросов вместо нескольких больших (уберите соединения — joins).
- Разделяйте базы данных.
- Создавайте новые фичи в виде микросервисов, прототипов.
- Замените код в старой системе на API-вызовы новых микросервисов.
- Протестируйте в безумных условиях и под сумасшедшей нагрузкой.
- Долгосрочные цели (Чед Фаулер)
- Это должно работать.
- Это должно работать быстро.
- Это должно быть дешёвым => спотовые экземпляры (spot instances) AWS экономят от 85 до 95 % серверных узлов.
- Производительность (Чед Фаулер)
- Повышайте скорость разработки и развёртывания с помощью Docker.
Заключение
В большинстве проектов не требуется микросервисная архитектура, им нужна хорошая архитектура. Под этим я подразумеваю не только хорошую структуру, но также (может, это даже важнее) ясное определение этой структуры, чёткое и аккуратное отражение структуры в самом коде, чтобы это было очевидно для разработчиков и помогло им выделить ограниченные контексты и понять, когда стоит пересекать границы, а когда нет.
А дальше уже разработчикам решать, поддерживать или развивать архитектурную структуру. Это подразумевает строгое следование плану, структуре, архитектуре, что не всегда легко. Ведь мы всего лишь люди.
Полезные ссылки
Статьи
Werner Vogels • декабрь 2008 • Eventually Consistent – Revisited
Oracle • июнь 2012 • De-mystifying “eventual consistency” in distributed systems
Мартин Фаулер и Джеймс Льюис • март 2014 • Microservices
Конференции
Эдриан Кокрофт • январь 2015 • The State of the Art in Microservices
Чед Фаулер • июль 2015 • From Homogeneous Monolith to Radically Heterogeneous Microservices Architecture
Эрик Эванс • декабрь 2015 • DDD & Microservices: At Last, Some Boundaries!
Фред Джордж • август 2015 • Challenges in implementing Microservices
Джеймс Льюис • октябрь 2015 • Microservices and the Inverse Conway Manoeuvre
Джет Уэсли-Смит • октябрь 2014 • Real World Microservices
Мартин Фаулер • январь 2015 • Microservices
Рейчел Майерс • декабрь 2015 • Stop Building Services, Episode 1: The Phantom Menace
Ребекка Парсонс • июль 2015 • Evolutionary Architecture & Micro-Services