Микросервисная архитектура что это
Просто о микросервисах
Вступление
Чуть ли не каждый второй, кто впервые сталкивается с MSA (Micro Service Architecture), на первых порах восклицает: «Да я эти микросервисы еще …надцать лет назад». Отчасти они правы. И я тоже был из этой самой половины, и не понимал — почему такой шум?
В самом деле! Ведь MSA — это тоже про разработку софта. Какие здесь могут быть революции? Все методики знакомы. В некоторых местах можно даже удивиться: «А разве бывает по-другому»? Фанаты Agile и DevOps тоже скажут, что это всё наше, родное.
Но всё же прошу вас набраться терпения и продолжить читать дальше.
Что такое микросервисная архитектура (MSA)
MSA — принципиальная организация распределенной системы на основе микросервисов и их взаимодействия друг с другом и со средой по сети, а также принципов, направляющих проектирование архитектуры, её создание и эволюцию.
Что такое микросервис (MS)
Понять суть микросервиса проще всего на сравнении, или даже противопоставлении его крупному приложению — монолиту. В отличии от MSA, я не буду давать определение микросервису, а перечислю его наиболее важные характеристики.
А дальше мы рассмотрим каждую из них подробнее.
Я выделил восемь свойств микросервиса:
Небольшой
Что такое «небольшой»? Такая малоинформативная формулировка! На самом деле, по-другому не скажешь. Каждый должен самостоятельно определиться с размером. Лучше всего на практике. В качестве индикативных оценок можно ориентироваться на рекомендации экспертов. Размер микровервиса должен быть таким, чтобы выполнялось одно из условий:
Независимый
Микросервисная архитектура — воплощение паттернов High Cohesion и Low Coupling. Всё, что противоречит этому, отвергается беспощадно. В противном случае команду ждут большие проблемы. Так что микросервис обязан быть независимым компонентом.
Здесь попрошу вас не начинать холивар о том, что же такое «компонент». Давайте в рамках этой статьи сойдемся на том, что
Компонент — это единица ПО, код которой может быть независимо заменен или обновлен.
Конечно любая мало-мальски серьезная программа пишется с разбиением на компоненты, которые, безусловно, основываются на тех же принципах. Но в монолите общая кодовая база открывает возможности для нарушения низкой связанности. И при слабой дисциплине рано или поздно код превращается в спагетти.
Под такую формулировку компонента подходят и сторонние библиотеки. Здесь сложнее с нарушением границ произвольными связями, но не на много.
В то же время методология разбиения на отдельные микросервисы вынуждает придерживаться жесткого их разделения, ведь они должны отвечать более жестким критериям независимости.
Так, каждый микросервис работает в своем процессе и поэтому должен явно обозначить свой API. Учитывая, что другие компоненты могут использовать только этот API, и к тому же он удаленный, минимизация связей становится жизненно важной.
Такое разделение дает явный выигрыш с точки зрения независимого развития разных компонентов. И с учетом этого различные языки вводят конструкции, позволяющие явное создание независимых компонентов (например, модули в Java 9), и это перестает быть прерогативой микросервисного подхода.
Не хочу, чтобы создалось впечатление, будто в микросервисной архитектуре запрещено использование библиотек. Их использование не приветствуется, поскольку так или иначе приводит к зависимостям между микросервисами, но всё же допускается. Как правило, это допущение распространяется на инфраструктурные функции вроде логирования, вызова удаленного API, обработки ошибок и тому подобного.
Независимость микросервисов позволяет организовать независимый жизненный цикл разработки, создавать отдельные сборки, тестировать и развертывать.
Поскольку размер микросервисов невелик, то очевидно, что в крупных системах их будет немало. Управлять ими вручную будет сложно. Поэтому команда обязана иметь приемлемый уровень автоматизации согласно Continuous integration и Continuous Delivery.
Где же микросервис (бизнес-потребность)
Итак, вы решили спроектировать новый микросервис.
Определение его границ — самый важный шаг. От этого будет зависеть вся дальнейшая жизнь микросервиса, и это серьёзно повлияет на жизнь команды, отвечающей за него.
Основной принцип определения зоны ответственности микросервиса — сформировать её вокруг некоторой бизнес-потребности. И чем она компактнее, чем формализованней её взаимоотношения с другими областями, тем проще создать новый микросервис. В общем, довольно стандартный посыл. На нем основывается создание любых других компонентов. Вопрос только в том, чтобы в дальнейшем выдержать эту зону ответственности, что мы и обсуждали в предыдущем параграфе.
Когда границы микросервиса заданы и он выделен в отдельную кодовую базу, защитить эти границы от постороннего влияния не составляет труда. Далее внутри микросервиса создают свой микромир, опираясь на паттерн «ограниченного контекста». В микросервисе для любого объекта, для любого действия может быть своя интерпретация, отличная от других контекстов.
Но что делать, если границы оказались неправильными? В этом случае изменение функциональности в новом микросервисе ведет к изменению функциональности в других микросервисах. В результате «поплывут» интерфейсы всех зависимых микросервисов, а за ними интеграционные тесты. И всё превращается в снежный ком. А если эти микросервисы ещё и принадлежат разным командам, то начинаются межкомандные встречи, согласования и тому подобное. Так что правильные границы микросервиса — это основа здоровой микросервисной архитектуры.
Чтобы минимизировать ошибки при определении границ, нужно вначале их продумать. Поэтому оправданным является подход Monolith First, когда вначале систему развивают в традиционной парадигме, а когда появляются устоявшиеся области, их выделяют в микросервисы. Но всё течет и меняется. И границы тоже могут меняться. Главное, чтобы выигрыш от разбиения превышал сложности пересмотра этих границ. Такой подход к постепенному формированию набора микросервисов похож на итерационное развитие, используемое в Agile, ещё его называют «эволюционным проектированием» (Evolutionary Design).
Есть ещё одно интересное следствие создания микросервисов, соответствующее закону Конвея (Conwey Law).
Если организация использует монолитное приложение, то оно нарушает соответствие структуре и коммуникациям внутри организации. А команды разработчиков строятся вокруг архитектурных слоев монолита: UI, серверная логика, база данных.
Микросервисная архитектура приводит IT и бизнес в гармонию, с точки зрения Конвея. Поскольку микросервисы формируются вокруг бизнес-потребностей конкретных бизнес-подразделений, то архитектура предприятия начинает повторять оргструктуру и каналы социальной и бизнес-коммуникации. А команды становятся кроссфункциональными и формируются вокруг этих бизнес-потребностей / бизнес-подразделений.
Поскольку разные микросервисы получаются независимыми не только логически, но и технологически, а создавать их могут разные команды, ничто не мешает для каждого случая подбирать подходящие языки программирования, фреймворки и даже операционные системы.
Интеграция. Smart endpoints and dumb pipes
Интеграция микросервисов обходится без ESB, как центрального промежуточного звена. Наверное, комьюнити уже натерпелось от неудачных вариантов реализации этого подхода. То, что были и удачные — не принимается в расчет. Впрочем, ESB ещё и противоречит таким критериям как децентрализация и независимость. Таким образом, сложность интеграции распределяется с центрального звена в виде ESB непосредственно на интегрируемые компоненты: «умные конечные точки».
Здесь есть дилемма. Конечно бинарные протоколы гораздо эффективнее. Но, во-первых, появляются технологические ограничения. Во-вторых, на бинарных протоколах сложнее реализовывать шаблон Tolerant Reader, сохраняя эффективность. В-третьих, опять появляется зависимость провайдера и потребителей, поскольку они оперируют одними и теми же объектами и методами, то есть связаны по кодовой базе.
Другая отличительная черта взаимодействия микросервисов — синхронные вызовы не приветствуются. Рекомендуется использовать один синхронный вызов на один запрос пользователя, или вообще отказаться от синхронных вызовов.
И еще пара замечаний.
Design for failure для распределенной системы
Одно из наиболее критичных мест в микросервисной архитектуре — необходимость разрабатывать код для распределенной системы, составные элементы которой взаимодействуют через сеть.
А сеть ненадежна по своей природе. Сеть может просто отказать, может работать плохо, может вдруг перестать пропускать какой-то тип сообщений, потому что изменились настройки файрвола. Десятки причин и видов недоступности.
Поэтому микросервисы могут вдруг перестать отвечать, могут начать отвечать медленнее, чем обычно. И каждый удаленный вызов должен это учитывать. Должен правильно обрабатывать разные варианты отказа, уметь ждать, уметь возвращаться к нормальной работе при восстановлении контрагента.
Дополнительный уровень сложности привносит событийная архитектура. А отладку такой системы — не одного микросервиса, а системы, где много потоков разнонаправленных неупорядоченных событий — даже трудно представить. И даже если каждый из микросервисов будет безупречен с точки зрения бизнес-логики, этого мало. По аналогии со спортом, «звёзды» не гарантируют звездную команду, ведь в команде важнее не «звезды», а слаженность всех её игроков.
И поскольку сложность таких систем очень высока, то проблему решают так.
Децентрализация данных
Каждому микросервису по своей базе данных!
Лозунг популиста на выборах.
На самом деле и в монолите можно побороться за изолированность компонентов, например, на уровне серверного кода. Если время от времени изоляция даёт течь, современные инструменты предлагают продвинутые инструменты рефакторинга. Пользуйтесь. Хотя, как правило, на это находится время, только когда дела уже совсем плохи.
Теперь опустимся ниже, на уровень базы данных. Почему-то здесь на изолированность обращают внимание гораздо реже. В результате через пару тройку лет активного развития в базе данных монолита образуется если не хаос, то энтропия продвинутого уровня. Чтобы её побороть, мало уже одной строчки в бэклоге. Необходимы месяцы кропотливого и долгого труда.
В микросервисной архитектуре это решается гильотиной. Общей базы данных просто нет.
Помимо изолированности есть и побочные плюсы. Например, легче реализовать Polyglot Persistence, когда база подбирается под конкретные цели. Ничто не мешает делать это и без микросервисов, и так часто делают. Но всё же в одном случае это закон, в другом — исключение.
У этой медали есть оборотная сторона. Много баз, много контекстов, как их все согласовать? Старая техника распределенных транзакций сложна и обладает низкой скоростью. Возможно это иногда можно пережить. А вот необходимость синхронного взаимодействия нескольких микросервисов не может устраивать, и это не побороть.
Проблема решается нетрадиционно для монолита: отказом от постоянной согласованности данных. Добро пожаловать в мир Eventual consistency. На первых порах это вызывает волну «справедливого» гнева. Но если разобраться, то нужна ли повсеместно немедленная согласованность данных по окончании транзакции? При детальном рассмотрении значительную часть случаев можно отбросить. Где возможно, заменяют одну распределённую транзакцию серией локальных с компенсационными механизмами. Где-то мирятся с временной несогласованностью. А возможные ошибки либо обрабатывают за счет более сложной архитектуры, либо благодаря данным мониторинга. Если ничего не получается, то в особо экстремальных случаях всё же используют распределенные транзакции. Но это, с моей точки зрения, нарушение принципов MSA.
Монолит против микросервисов
Микросервисный подход несет довольно много проблем. Их найти не трудно и каждый может поупражняться.
Например, организационные вопросы. Как удержать в согласованном по версиям состоянии сотню микросервисов, которые еще и постоянно и непредсказуемо редеплоятся. А доступ к средам у каждого инженера каждой команды? Какая команда напишет интеграционные тесты? И если кто-то согласится, то попробуй еще их напиши для такой запутанной конфигурации. А если возникает ошибка, то чья она? Только той команды, у которой сломалось? Как не узнать вечером в пятницу, что версия API N-го сервиса, которой вы пользуетесь, вдруг стала deprecated?
Да, это действительно проблемы. Но команды, которые практикуют Agile и DevOps, уже знают решение. Поэтому начинать путь к микросервисной архитектуре стоит с внедрения этих практик.
Кроме организационных есть и чисто архитектурные. Как перейти от монолита, где всё синхронно, согласованно и едино, к распределенной событийной архитектуры, основанной на множестве мелких элементов, в которой надо учитывать возможную неконсистентность данных? Одного этого достаточно, чтобы задуматься: а стоит ли игра свеч? На этом фоне, например, падение скорости обработки одного запроса кажется мелочью. Хотя бы работает!
Тогда зачем? Если у вас нет проблем с вашим «монолитом», то не надо их искать.
Но если проблемы есть, то посмотрите на плюсы MSA, и возможно она спасет вас.
Разбиение на независимые компоненты даёт безусловные и неоспоримые преимущества: легкое понимание контекста, гибкость развития, управления и масштабирования. Независимость и небольшой размер дают и неожиданные плюсы с точки зрения инфраструктуры. Вам теперь не нужна монструозная машина за 100500 долларов. Микросервисы можно устанавливать на обычные дешевые машинки. И окажется, что даже все вместе они будут стоить на порядок меньше, но работать эффективнее той самой супермашины, на которую у вас в организации, наверняка, молятся и сдувают с неё пылинки.
Здесь уместен другой лозунг от популиста. Хотя, как и предыдущий, он вполне серьезен.
Каждому микросервису по своему серверу!
Продолжим агитировать за микросервисы. Посмотрим на лидеров IT-индустрии: Amazon, Netflix, Google и другие показывают впечатляющие результаты. Их гибкость и скорость вывода новых продуктов поражают. Поэтому игра точно стоит свеч! Здесь уместно вспомнить, что в упомянутых организациях команд «уровня бог» не одна и не две. Им сложности микросервисной архитектуры вполне по зубам. И если предложить создать монолит, то они и его сделают так, что он будет сверкать путеводной звездой.
А, например, Amazon вполне себе работал на монолите, уже будучи гигантом и имея миллиардные обороты. Сайт газеты Guardian до сих пор, а возможно и навсегда, базируется на микросервисах вокруг монолита. Это говорит о том, что значительная часть задач успешно, а зачастую и легче, решается без привлечения микросервисов.
И всё же это не значит, что микросервисы не для вас. Не боги горшки обжигают. Но бросаться с головой в омут тоже не стоит. Для микросервисной архитектуры команда должна быть достаточно зрелой. Один из главных критериев: использует ли она Agile и DevOps? Команда должна быть грамотной. Это сложно формализовать, но всё же попробуйте трезво оценить возможности. Например, насколько команда продвинута в Reactive и Event-Driven Architecture? К тому же команда должна иметь подготовленную инфраструктуру для поддержки микросервисной системы.
Впрочем, достаточно. Просто попробуйте. Надеюсь, получится и понравится.
Архитектура микросервисов
К сожалению, у меня нет опыта работы с микросервисами, но около года назад я очень активно интересовался этой темой и изучил все источники информации, какие смог найти. Я просмотрел несколько выступлений на конференциях, прочитал несколько статей очень авторитетных и опытных специалистов вроде Мартина Фаулера, Фреда Джорджа, Эдриана Кокрофта и Криса Ричардсона, чтобы как можно больше узнать о микросервисах. Эта статья — результат моих изысканий.
Содержание
Иными словами, мы инкапсулируем определённые контексты приложения в микросервисы, по одному на каждый, а сами микросервисы крутим на разных серверах.
SOA и микросервисы
Согласно Мартину Фаулеру, термином SOA злоупотребляют все кому не лень, сегодня под ним подразумевают множество вещей. С точки зрения Мартина, микросервисы — это разновидность SOA.
Когда следует использовать микросервисы?
Как архитектор-теоретик, желающий стать практиком, я считаю следующее. Решая, использовать ли микросервисы, ни в коем случае нельзя руководствоваться мифами, или желанием «в следующий раз попробовать это», или стремлением быть на переднем крае технологий. К этому, в соответствии с выводами Рейчел Майерс, нужно подходить исключительно с прагматической точки зрения. Рейчел отмечает, что архитектура должна:
Мартин Фаулер выделяет несколько преимуществ монолитной и микросервисной архитектур, что поможет вам решить, какой подход выбрать:
Преимущества | |
Монолитная архитектура | Микросервисы |
Простота |
Монолитная архитектура гораздо проще в реализации, управлении и развёртывании.
Микросервисы требуют тщательного управления, поскольку они развёртываются на разных серверах и используют API.
Микросервисы позволяют по мере необходимости обновлять приложение по частям.
При единой архитектуре нам приходится заново развёртывать приложение целиком, что влечёт за собой куда больше рисков.
При монолитной архитектуре проще поддерживать согласованность кода, обрабатывать ошибки и т. д. Зато микросервисы могут полностью управляться разными командами с соблюдением разных стандартов.
У микросервисов доступность выше: даже если один из них сбоит, это не приводит к сбою всего приложения.
Единая архитектура облегчает работу в ситуациях, когда несколько модулей должны взаимодействовать между собой или когда мы хотим переместить классы из одного модуля в другой. В случае с микросервисами мы должны очень чётко определять границы модулей!
Сохранять модульность и инкапсуляцию может быть непросто, несмотря на правила SOLID. Однако микросервисы позволяют гарантировать отсутствие общих состояний (shared state) между модулями.
Микросервисы позволяют использовать разные технологии и языки, в соответствии с вашими задачами.
Микросервисы | |
Аппаратные преимущества | Программные преимущества |
Независимая масштабируемость |
При размещении модулей на отдельных серверных узлах мы можем масштабировать их независимо от других модулей.
И единая, и микросервисная архитектуры позволяют сохранять модульность и инкапсуляцию. Однако это может быть довольно трудной задачей, на решение которой уйдут десятилетия, несмотря на правила SOLID. Зато микросервисы позволяют обеспечивать логическое разделение приложения на модули за счёт явного физического разделения по серверам. Физическая изолированность защищает от нарушения пределов ограниченных контекстов.
Благодаря распределению модулей по разным серверным узлам и независимому языку взаимодействия мы можем использовать совершенно разные языки программирования, инструменты взаимодействия, мониторинга и хранения данных. Это позволяет выбирать лучшие и наиболее удобные решения, а также экспериментировать с новыми технологиями.
Микросервис может развиваться и ломать обратную совместимость, не обременяя себя поддержкой старых версий, так как всегда можно оставить старую версию микросервиса работающей необходимое время.
Я считаю, что основные причины для использования микросервисов — аппаратные преимущества, недостижимые с помощью единой архитектуры. Так что если вам важны вышеописанные моменты, то микросервисы безальтернативны. Если же аппаратные преимущества для вас некритичны, то сложность микросервисной архитектуры может перевесить её достоинства. Также мне кажется, что с помощью единой архитектуры невозможно достичь частичного развёртывания и частичной доступности, характерных для микросервисов. Это не ключевые преимущества (хотя это в любом случае преимущества).
Вне зависимости от наших вкусов и пожеланий НЕЛЬЗЯ начинать новый проект сразу с использованием микросервисной архитектуры. Вначале нужно сосредоточиться на понимании задачи и на способе её достижения, не тратя ресурсы на преодоление огромной сложности создания экосистемы микросервисов (Ребекка Парсонс, Саймон Браун).
Предпосылки
Непрерывное развёртывание
Возможность и нацеленность на постоянное ускорение работы
Одна из причин использования микросервисов заключается в том, что мы хотим иметь возможность быстро что-то менять, чтобы реагировать на изменения бизнес-требований, опережать конкурентов. Или, выражаясь словами Эрика Эванса, нам нужно осознавать хаос в компаниях:
Реальность разработки ПО такова, что вначале мы никогда не имеем полного понимания задачи. Наше понимание углубляется по мере работ, и нам постоянно приходится рефакторить. Так что рефакторинг — это потребность, но в то же время и опасность, потому что код становится запутанней, особенно при несоблюдении ограниченности контекстов. Микросервисы заставляют соблюдать пределы ограниченных контекстов, что позволяет сохранять работоспособность, ясность, изолированность и инкапсулированность кода в отдельных связных модулях. Если модуль/микросервис становится запутанным, то эта запутанность только в нём и остаётся, а не распространяется за его пределы.
Нам нужно действовать быстрее на всех стадиях разработки! Это верно для любой архитектуры, но микросервисы в этом отношении удобнее. Мартин Фаулер говорит, что необходимо иметь возможность:
Фред Джордж утверждает то же самое: есть огромная потребность ускорить работу, чтобы выдержать конкуренцию! Он приводит ретроспективный анализ времени, необходимого на введение в эксплуатацию сервера, и отмечает, что в 1990-х требовалось 6 месяцев, в 2010-м благодаря облачным сервисам — 30 минут, а в 2015-м Docker позволял поднять и запустить новый сервер менее чем за минуту.
Эдриан Кокрофт, один из ключевых специалистов в Netflix Cloud и пионер в освоении микросервисов, отмечает, как важно находиться в первых рядах при освоении новых технологий, а также очень быстро вводить новые серверы и развёртывать новые версии своих приложений. Эдриан — большой поклонник Docker, поскольку этот сервис позволяет за секунды создавать сервер и развёртывать среды для разработки, тестирования и работы.
Усложнившийся мониторинг
Мониторинг крайне важен (Ребекка Парсонс), нам необходимо сразу узнавать о том, что сервер упал, что какой-то компонент перестал отвечать, что происходят сбои вызовов, причём по каждому из микросервисов (Фред Джордж). Также нам нужны инструменты для быстрой отладки (Мартин Фаулер).
Сильная devops-культура
Нам нужны devops’ы для мониторинга и управления, при этом между ними и разработчиками должны быть тесные отношения и хорошее взаимодействие (Мартин Фаулер). При работе с микросервисами нам приходится больше развёртывать, усложняется система мониторинга, сильно разрастается количество возможных сбоев. Поэтому в компании очень важна сильная devops-культура (Ребекка Парсонс).
Характеристики
Мартин Фаулер и Джеймс Льюис в своей широко известной статье и выступлениях (Фаулер, Льюис) приводят набор характеристик для определения микросервиса.
Что такое микросервис?
Архитектура на основе свободно сопряжённых сервисов с ограниченными контекстами. (Loosely coupled service oriented architecture with bounded contexts.)
Ограниченный контекст — это понятие явных границ вокруг какого-то бизнес-контекста. Например, в рамках электронной коммерции мы оперируем понятиями «темы» (themes), «поставщики платёжных услуг» (payment providers), «заказы», «отгрузка», «магазин приложений». Всё это ограниченные контексты, а значит — кандидаты в микросервисы.
Полезная общая информация о микросервисах приводится в книге Сэма Ньюмена «Building Microservices». По мнению Джеймса Льюиса, микросервисы должны:
Насколько велик микросервис?
Джеймс Льюис утверждает, что сервис должен быть «настолько большим, чтобы умещаться в руке», то есть чтобы один человек мог полностью разобраться в его устройстве и работе.
Есть разные мнения о размерах микросервисов. Мартин Фаулер описывает случаи, когда соотношение количества сотрудников и сервисов колебалось от 60 к 20 до 4 к 200. К примеру, в Amazon используется подход с «командами на две пиццы» (two pizzas team): в команде микросервиса должно быть столько людей, чтобы их можно было накормить двумя пиццами.
Фред Джордж полагает, что микросервис должен быть «очень-очень маленьким», чтобы его создавал и сопровождал только один разработчик. То же самое говорит и Джеймс Льюис.
Я согласен с Джеймсом Льюисом, Фредом Джорджем и Эдрианом Кокрофтом. Мне кажется, микросервис должен соответствовать ограниченному контексту, который способен полностью понять один человек. То есть чем шире функциональность приложения, тем больше должно быть микросервисов. Например, в Netflix их около 800! (Фред Джордж)
Тем не менее как в самом начале жизненного цикла микросервиса, так и позднее ограниченный контекст может оказаться слишком велик для понимания одним человеком. Нужно выявлять такие ситуации и дробить подобные сервисы на более мелкие. Это соответствует концепциям архитектуры с эволюционным развитием и DDD, подразумевающим, что архитектура постоянно меняется/рефакторится по мере углубления в задачу и/или изменений бизнес-требований. Как говорит Ребекка Парсонс, «дробление крайне важно»: при разработке микросервисов труднее всего определять их границы. И при продвижении работы мы однозначно будем объединять или дробить сервисы.
Компонентное представление через сервисы
Гетерогенность
Гетерогенность — это возможность построить систему с использованием разных языков программирования. У подхода есть ряд преимуществ (Мартин Фаулер), а Чед Фаулер считает, что системы обязаны быть гетерогенны по умолчанию, то есть разработчики должны стараться применять новые технологии.
Преимущества гетерогенной системы:
Организация человеческих ресурсов в соответствии с возможностями бизнеса
Когда-то внутри команд разработчиков самоорганизовывались группы на основе используемых технологий. В результате проект создавали команда по DBA, команда разработки серверной части и команда разработки интерфейса, действовавшие независимо друг от друга. Такая схема сказывается на качестве продукта, потому что знания в конкретных областях и усилия по разработке рассеиваются по подгруппам.
При микросервисном подходе команды должны организовываться на основе бизнес-возможностей: например команда заказов, отгрузки, каталога и т. д. В каждой команде должны быть специалисты по всем необходимым технологиям (интерфейс, серверная часть, DBA, QA. ). Это даст каждой команде достаточный объём знаний, чтобы сосредоточиться на создании конкретных частей приложения — микросервисов (Мартин Фаулер, Эрик Эванс).
Подход сочетается с законом Конвея, который гласит, что если нам нужны высокосвязные раздельные микросервисы, то структура организации должна отражать желаемую компонентную структуру.
Организации, разрабатывающие системы… создают архитектуры, которые копируют структуры взаимодействий внутри этих организаций.
Продукты, а не проекты
Раньше был такой подход: команда создаёт какую-то функциональность, а затем передаёт её на сопровождение другой команде.
В случае с микросервисами команда должна отвечать за свой продукт в течение всего его жизненного цикла, включая разработку, сопровождение и вывод из эксплуатации. Это формирует «продуктовое мышление», что означает сильную связь между техническим продуктом и его бизнес-возможностями. То есть создаётся прямая взаимосвязь: как приложение помогает своим пользователям расширить их бизнес-возможности.
Умные эндпойнты и глупые каналы (Smart endpoints and dumb pipes)
Опять же, в старые добрые времена компании использовали архитектуру Enterprise Service Bus (сервисная шина), при которой формируется канал коммуникаций между эндпойнтами и бизнес-логикой. Затем этот подход преобразился в spaghetti box.
Микросервисная архитектура переносит бизнес-логику в конечные точки и использует простые способы взаимодействия вроде HTTP.
Децентрализованное управление
Ключевые решения по микросервисам должны принимать люди, которые действительно разрабатывают микросервисы. Здесь под ключевыми решениями подразумевается выбор языков программирования, методологии развёртывания, контрактов публичных интерфейсов и т. д.
Децентрализованное управление данными
При традиционном подходе у приложения лишь одна база данных, и много разных компонентов бизнес-логики приложения «взаимодействуют» в рамках этой БД: напрямую читают из неё данные, принадлежащие другим компонентам. Это также означает, что для всех компонентов характерна одна и та же степень сохранности данных, даже если для каких-то из них это не самая лучшая ситуация (Мартин Фаулер).
При микросервисной архитектуре, когда каждый бизнес-компонент представляет собой микросервис, все компоненты обладают собственными базами данных, которые недоступны другим микросервисам. Данные компонента доступны (для чтения и записи) только через соответствующий интерфейс компонентов. Благодаря этому степень устойчивости данных варьируется в зависимости от компонента (Мартин Фаулер, Чед Фаулер).
С точки зрения Фреда Джорджа, это первый вызов на пути к микросервисной архитектуре.
Автоматизация инфраструктуры
Страховка от сбоев (Design for failure)
Серверы, по которым распределено приложение, рано или поздно падают, особенно разные узлы. Поэтому архитектура приложений должна быть устойчива к таким сбоям (Мартин Фаулер).
Chaos monkey — это инструмент, созданный в Netflix. Он позволяет выключать серверы для проверки устойчивости системы к такому типу отказов (Мартин Фаулер).
Ребекка Парсонс считает очень важным, что мы больше не используем даже внутрипроцессное взаимодействие между сервисами, вместо этого для связи мы прибегаем к HTTP, который и близко не бывает столь же надёжен. В результате будут возникать сбои при общении сервисов друг с другом, и система должна быть к этому готова.
Архитектура с эволюционным развитием
Архитектура всего приложения не должна быть статичной, необходима возможность её простого развития в соответствии с потребностями бизнеса. Например, можно:
Фронтенд/бэкенд
Есть два подхода к структурированию фронтенда и бэкенда при микросервисной архитектуре:
Опасности
Нужно управлять гибкостью технологии
Одно из преимуществ микросервисов заключается в том, что мы можем применять разные технологии для решения одной и той же задачи. Например, в каждом микросервисе использовать разные библиотеки для XML-парсинга или разные инструменты сохранности данных. Но сама возможность не означает, что мы должны это делать. Не исключено, что обилие технологий и библиотек выйдет из-под контроля. Так что выберите базовый набор инструментов и обращайтесь к другим только тогда, когда это действительно нужно (Ребекка Парсонс).
Нужно управлять нестабильностью интерфейса
В начале разработки микросервиса его API особенно нестабилен. Но даже на более поздних стадиях, когда микросервис достаточно отработан, нам приходится менять API, его ввод и вывод. Осторожно вносите изменения, потому что другие приложения будут полагаться на стабильность API (Ребекка Парсонс).
Необходимо быть уверенными в согласованности данных
Микросервисы имеют собственные хранилища данных. И во многих случаях данные, принадлежащие одному микросервису, будут частично или целиком скопированы другим, клиентским микросервисом. Когда данные у поставщика меняются, он инициирует событие для запуска обновления данных, скопированных клиентским микросервисом. Событие попадает в очередь сообщений и ожидает, когда его получит клиентский микросервис.
Эта схема означает, что клиентский микросервис будет обладать устаревшими данными, пока не обнаружит нужное событие. Данные не согласованы.
Конечно, в итоге изменения будут применены ко всем копиям, а данные снова станут согласованными. Это называется eventual consistency — согласованность в конечном счёте. То есть мы знаем, что в течение короткого периода времени данные остаются несогласованными. Этот эффект имеет важное значение в ходе разработки приложений, от серверной части до UX-уровней (Ребекка Парсонс).
Как декомпозировать единое приложение
Приступая к созданию приложения, нужно изначально придерживаться единой архитектуры — по причине её простоты. В то же время нужно стараться создавать его как можно более модульным, чтобы каждый компонент легко переносился в отдельный микросервис (Ребекка Парсонс). Это сочетается с идеей Саймона Брауна о разработке приложения в виде набора раздельных компонентов в едином развёртываемом модуле.
При декомпозиции единой архитектуры в микросервисную, или в набор раздельных компонентов, необходимо думать о нескольких измерениях в поддержку нашего решения:
Заключение
В большинстве проектов не требуется микросервисная архитектура, им нужна хорошая архитектура. Под этим я подразумеваю не только хорошую структуру, но также (может, это даже важнее) ясное определение этой структуры, чёткое и аккуратное отражение структуры в самом коде, чтобы это было очевидно для разработчиков и помогло им выделить ограниченные контексты и понять, когда стоит пересекать границы, а когда нет.
А дальше уже разработчикам решать, поддерживать или развивать архитектурную структуру. Это подразумевает строгое следование плану, структуре, архитектуре, что не всегда легко. Ведь мы всего лишь люди.