company_banner

Архитектура микросервисов

https://herbertograca.com/2017/01/26/microservices-architecture/
  • Перевод


К сожалению, у меня нет опыта работы с микросервисами, но около года назад я очень активно интересовался этой темой и изучил все источники информации, какие смог найти. Я просмотрел несколько выступлений на конференциях, прочитал несколько статей очень авторитетных и опытных специалистов вроде Мартина Фаулера, Фреда Джорджа, Эдриана Кокрофта и Криса Ричардсона, чтобы как можно больше узнать о микросервисах. Эта статья — результат моих изысканий.

Содержание



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

Иными словами, мы инкапсулируем определённые контексты приложения в микросервисы, по одному на каждый, а сами микросервисы крутим на разных серверах.

SOA и микросервисы


Согласно Мартину Фаулеру, термином SOA злоупотребляют все кому не лень, сегодня под ним подразумевают множество вещей. С точки зрения Мартина, микросервисы — это разновидность SOA.

Когда следует использовать микросервисы?


Как архитектор-теоретик, желающий стать практиком, я считаю следующее. Решая, использовать ли микросервисы, ни в коем случае нельзя руководствоваться мифами, или желанием «в следующий раз попробовать это», или стремлением быть на переднем крае технологий. К этому, в соответствии с выводами Рейчел Майерс, нужно подходить исключительно с прагматической точки зрения. Рейчел отмечает, что архитектура должна:

  • делать продукт гибче и устойчивее к сбоям;
  • облегчать понимание, отладку и изменение кода;
  • помогать в командной работе.

Я согласен с Рейчел, но я также считаю, что этим критериям удовлетворяют и монолитные архитектурные схемы.

Мартин Фаулер выделяет несколько преимуществ монолитной и микросервисной архитектур, что поможет вам решить, какой подход выбрать:
Преимущества
Монолитная архитектура Микросервисы
Простота

Монолитная архитектура гораздо проще в реализации, управлении и развёртывании.

Микросервисы требуют тщательного управления, поскольку они развёртываются на разных серверах и используют API.
Частичное развёртывание

Микросервисы позволяют по мере необходимости обновлять приложение по частям.

При единой архитектуре нам приходится заново развёртывать приложение целиком, что влечёт за собой куда больше рисков.
Согласованность (Consistency)

При монолитной архитектуре проще поддерживать согласованность кода, обрабатывать ошибки и т. д. Зато микросервисы могут полностью управляться разными командами с соблюдением разных стандартов.
Доступность

У микросервисов доступность выше: даже если один из них сбоит, это не приводит к сбою всего приложения.
Межмодульный рефакторинг

Единая архитектура облегчает работу в ситуациях, когда несколько модулей должны взаимодействовать между собой или когда мы хотим переместить классы из одного модуля в другой. В случае с микросервисами мы должны очень чётко определять границы модулей!
Сохранение модульности

Сохранять модульность и инкапсуляцию может быть непросто, несмотря на правила SOLID. Однако микросервисы позволяют гарантировать отсутствие общих состояний (shared state) между модулями.
Мультиплатформенность/гетерогенность

Микросервисы позволяют использовать разные технологии и языки, в соответствии с вашими задачами.

Лично мне нравится прагматичный подход Эрика Эванса. Микросервисы с точки зрения аппаратных ресурсов имеют преимущества, которых лишены единые архитектуры, а также облегчают решение ряда задач с программной точки зрения:
Микросервисы
Аппаратные преимущества Программные преимущества
Независимая масштабируемость

При размещении модулей на отдельных серверных узлах мы можем масштабировать их независимо от других модулей.
Сохранение модульности

И единая, и микросервисная архитектуры позволяют сохранять модульность и инкапсуляцию. Однако это может быть довольно трудной задачей, на решение которой уйдут десятилетия, несмотря на правила SOLID. Зато микросервисы позволяют обеспечивать логическое разделение приложения на модули за счёт явного физического разделения по серверам. Физическая изолированность защищает от нарушения пределов ограниченных контекстов.
Независимый технический стек

Благодаря распределению модулей по разным серверным узлам и независимому языку взаимодействия мы можем использовать совершенно разные языки программирования, инструменты взаимодействия, мониторинга и хранения данных. Это позволяет выбирать лучшие и наиболее удобные решения, а также экспериментировать с новыми технологиями.
Независимая эволюция подсистем

Микросервис может развиваться и ломать обратную совместимость, не обременяя себя поддержкой старых версий, так как всегда можно оставить старую версию микросервиса работающей необходимое время.

Я считаю, что основные причины для использования микросервисов — аппаратные преимущества, недостижимые с помощью единой архитектуры. Так что если вам важны вышеописанные моменты, то микросервисы безальтернативны. Если же аппаратные преимущества для вас некритичны, то сложность микросервисной архитектуры может перевесить её достоинства. Также мне кажется, что с помощью единой архитектуры невозможно достичь частичного развёртывания и частичной доступности, характерных для микросервисов. Это не ключевые преимущества (хотя это в любом случае преимущества).

Вне зависимости от наших вкусов и пожеланий НЕЛЬЗЯ начинать новый проект сразу с использованием микросервисной архитектуры. Вначале нужно сосредоточиться на понимании задачи и на способе её достижения, не тратя ресурсы на преодоление огромной сложности создания экосистемы микросервисов (Ребекка Парсонс, Саймон Браун).

Предпосылки


Непрерывное развёртывание


Возможность и нацеленность на постоянное ускорение работы

Одна из причин использования микросервисов заключается в том, что мы хотим иметь возможность быстро что-то менять, чтобы реагировать на изменения бизнес-требований, опережать конкурентов. Или, выражаясь словами Эрика Эванса, нам нужно осознавать хаос в компаниях:

Реальность разработки ПО такова, что вначале мы никогда не имеем полного понимания задачи. Наше понимание углубляется по мере работ, и нам постоянно приходится рефакторить. Так что рефакторинг — это потребность, но в то же время и опасность, потому что код становится запутанней, особенно при несоблюдении ограниченности контекстов. Микросервисы заставляют соблюдать пределы ограниченных контекстов, что позволяет сохранять работоспособность, ясность, изолированность и инкапсулированность кода в отдельных связных модулях. Если модуль/микросервис становится запутанным, то эта запутанность только в нём и остаётся, а не распространяется за его пределы.

Нам нужно действовать быстрее на всех стадиях разработки! Это верно для любой архитектуры, но микросервисы в этом отношении удобнее. Мартин Фаулер говорит, что необходимо иметь возможность:

  • Быстро вводить в эксплуатацию: быстро развёртывать новые машины для разработки, тестирования, приёмки и работы.
  • Быстро развёртывать приложения: автоматически и быстро развёртывать наши сервисы.



Фред Джордж утверждает то же самое: есть огромная потребность ускорить работу, чтобы выдержать конкуренцию! Он приводит ретроспективный анализ времени, необходимого на введение в эксплуатацию сервера, и отмечает, что в 1990-х требовалось 6 месяцев, в 2010-м благодаря облачным сервисам — 30 минут, а в 2015-м Docker позволял поднять и запустить новый сервер менее чем за минуту.

Эдриан Кокрофт, один из ключевых специалистов в Netflix Cloud и пионер в освоении микросервисов, отмечает, как важно находиться в первых рядах при освоении новых технологий, а также очень быстро вводить новые серверы и развёртывать новые версии своих приложений. Эдриан — большой поклонник Docker, поскольку этот сервис позволяет за секунды создавать сервер и развёртывать среды для разработки, тестирования и работы.

image

Усложнившийся мониторинг


Мониторинг крайне важен (Ребекка Парсонс), нам необходимо сразу узнавать о том, что сервер упал, что какой-то компонент перестал отвечать, что происходят сбои вызовов, причём по каждому из микросервисов (Фред Джордж). Также нам нужны инструменты для быстрой отладки (Мартин Фаулер).

Сильная devops-культура


Нам нужны devops’ы для мониторинга и управления, при этом между ними и разработчиками должны быть тесные отношения и хорошее взаимодействие (Мартин Фаулер). При работе с микросервисами нам приходится больше развёртывать, усложняется система мониторинга, сильно разрастается количество возможных сбоев. Поэтому в компании очень важна сильная devops-культура (Ребекка Парсонс).

Характеристики


Мартин Фаулер и Джеймс Льюис в своей широко известной статье и выступлениях (Фаулер, Льюис) приводят набор характеристик для определения микросервиса.

Что такое микросервис?


Лично я полностью согласен с определением Эдриана Кокрофта:

Архитектура на основе свободно сопряжённых сервисов с ограниченными контекстами. (Loosely coupled service oriented architecture with bounded contexts.)

image

Ограниченный контекст — это понятие явных границ вокруг какого-то бизнес-контекста. Например, в рамках электронной коммерции мы оперируем понятиями «темы» (themes), «поставщики платёжных услуг» (payment providers), «заказы», «отгрузка», «магазин приложений». Всё это ограниченные контексты, а значит — кандидаты в микросервисы.

Полезная общая информация о микросервисах приводится в книге Сэма Ньюмена «Building Microservices». По мнению Джеймса Льюиса, микросервисы должны:

  • дёшево заменяться;
  • быстро масштабироваться;
  • быть устойчивыми к сбоям;
  • никоим образом не замедлять нашу работу.

Насколько велик микросервис?


Джеймс Льюис утверждает, что сервис должен быть «настолько большим, чтобы умещаться в руке», то есть чтобы один человек мог полностью разобраться в его устройстве и работе.

Есть разные мнения о размерах микросервисов. Мартин Фаулер описывает случаи, когда соотношение количества сотрудников и сервисов колебалось от 60 к 20 до 4 к 200. К примеру, в Amazon используется подход с «командами на две пиццы» (two pizzas team): в команде микросервиса должно быть столько людей, чтобы их можно было накормить двумя пиццами.

Фред Джордж полагает, что микросервис должен быть «очень-очень маленьким», чтобы его создавал и сопровождал только один разработчик. То же самое говорит и Джеймс Льюис.

Я согласен с Джеймсом Льюисом, Фредом Джорджем и Эдрианом Кокрофтом. Мне кажется, микросервис должен соответствовать ограниченному контексту, который способен полностью понять один человек. То есть чем шире функциональность приложения, тем больше должно быть микросервисов. Например, в Netflix их около 800! (Фред Джордж)

Тем не менее как в самом начале жизненного цикла микросервиса, так и позднее ограниченный контекст может оказаться слишком велик для понимания одним человеком. Нужно выявлять такие ситуации и дробить подобные сервисы на более мелкие. Это соответствует концепциям архитектуры с эволюционным развитием и DDD, подразумевающим, что архитектура постоянно меняется/рефакторится по мере углубления в задачу и/или изменений бизнес-требований. Как говорит Ребекка Парсонс, «дробление крайне важно»: при разработке микросервисов труднее всего определять их границы. И при продвижении работы мы однозначно будем объединять или дробить сервисы.

Компонентное представление через сервисы


  1. Компонент — это элемент системы, который можно независимо заменить, усовершенствовать (Мартин Фаулер) и масштабировать (Ребекка Парсонс).
  2. При разработке ПО мы используем два типа компонентов:
    А. Библиотеки: куски кода, применяемые в приложениях, которые могут дополняться или заменяться другими библиотеками, желательно без воздействия на остальную часть приложения. Взаимодействие происходит через языковые конструкты. Однако если интересующая нас библиотека написана на другом языке, мы не можем использовать этот компонент.
    Б. Сервисы: части приложений, по факту представляющие собой маленькие приложения, выполняющиеся в собственных процессах. Взаимодействие выполняется за счёт межпроцессной связи, вызовов веб-сервисов, очереди сообщений и т. д. Мы можем использовать сервис, написанный на другом языке, поскольку он выполняется в собственном процессе (этот подход предпочитает Чед Фаулер).
  3. Независимая масштабируемость — каждый сервис может быть масштабирован независимо от остального приложения.

Гетерогенность


Гетерогенность — это возможность построить систему с использованием разных языков программирования. У подхода есть ряд преимуществ (Мартин Фаулер), а Чед Фаулер считает, что системы обязаны быть гетерогенны по умолчанию, то есть разработчики должны стараться применять новые технологии.

Преимущества гетерогенной системы:

  • Предотвращает возникновение тесных связей благодаря использованию разных языков.
  • Разработчики могут экспериментировать с технологиями, что повышает их собственную ценность и позволяет не уходить в другие компании, чтобы попробовать новинки.
    Правило. При экспериментах с новыми технологиями:
    — нужно использовать маленькие элементы кода (code unit), модули/микросервисы, чтобы снизить риск;
    — элементы кода должны быть одноразовыми (disposable).

Организация человеческих ресурсов в соответствии с возможностями бизнеса


Когда-то внутри команд разработчиков самоорганизовывались группы на основе используемых технологий. В результате проект создавали команда по DBA, команда разработки серверной части и команда разработки интерфейса, действовавшие независимо друг от друга. Такая схема сказывается на качестве продукта, потому что знания в конкретных областях и усилия по разработке рассеиваются по подгруппам.

При микросервисном подходе команды должны организовываться на основе бизнес-возможностей: например команда заказов, отгрузки, каталога и т. д. В каждой команде должны быть специалисты по всем необходимым технологиям (интерфейс, серверная часть, DBA, QA...). Это даст каждой команде достаточный объём знаний, чтобы сосредоточиться на создании конкретных частей приложения — микросервисов (Мартин Фаулер, Эрик Эванс).

Подход сочетается с законом Конвея, который гласит, что если нам нужны высокосвязные раздельные микросервисы, то структура организации должна отражать желаемую компонентную структуру.

Организации, разрабатывающие системы… создают архитектуры, которые копируют структуры взаимодействий внутри этих организаций.

Мелвин Конвей, 1967

Продукты, а не проекты


Раньше был такой подход: команда создаёт какую-то функциональность, а затем передаёт её на сопровождение другой команде.

В случае с микросервисами команда должна отвечать за свой продукт в течение всего его жизненного цикла, включая разработку, сопровождение и вывод из эксплуатации. Это формирует «продуктовое мышление», что означает сильную связь между техническим продуктом и его бизнес-возможностями. То есть создаётся прямая взаимосвязь: как приложение помогает своим пользователям расширить их бизнес-возможности.

Умные эндпойнты и глупые каналы (Smart endpoints and dumb pipes)


Опять же, в старые добрые времена компании использовали архитектуру Enterprise Service Bus (сервисная шина), при которой формируется канал коммуникаций между эндпойнтами и бизнес-логикой. Затем этот подход преобразился в spaghetti box.

Микросервисная архитектура переносит бизнес-логику в конечные точки и использует простые способы взаимодействия вроде HTTP.

Децентрализованное управление


Ключевые решения по микросервисам должны принимать люди, которые действительно разрабатывают микросервисы. Здесь под ключевыми решениями подразумевается выбор языков программирования, методологии развёртывания, контрактов публичных интерфейсов и т. д.

Децентрализованное управление данными


При традиционном подходе у приложения лишь одна база данных, и много разных компонентов бизнес-логики приложения «взаимодействуют» в рамках этой БД: напрямую читают из неё данные, принадлежащие другим компонентам. Это также означает, что для всех компонентов характерна одна и та же степень сохранности данных, даже если для каких-то из них это не самая лучшая ситуация (Мартин Фаулер).

При микросервисной архитектуре, когда каждый бизнес-компонент представляет собой микросервис, все компоненты обладают собственными базами данных, которые недоступны другим микросервисам. Данные компонента доступны (для чтения и записи) только через соответствующий интерфейс компонентов. Благодаря этому степень устойчивости данных варьируется в зависимости от компонента (Мартин Фаулер, Чед Фаулер).

С точки зрения Фреда Джорджа, это первый вызов на пути к микросервисной архитектуре.

image

Автоматизация инфраструктуры


Непрерывное развёртывание (Мартин Фаулер, Ребекка Парсонс, Чед Фаулер, Эрик Эванс):

  1. «Голубое» и «зелёное» развёртывание: нулевое время простоя.
  2. Автоматизация: нажатием одной кнопки можно развернуть несколько серверов.
  3. Серверы Phoenix: быстрый запуск и остановка.
  4. Мониторинг: можно заметить, когда что-то пошло не так, и отладить.

Страховка от сбоев (Design for failure)


Серверы, по которым распределено приложение, рано или поздно падают, особенно разные узлы. Поэтому архитектура приложений должна быть устойчива к таким сбоям (Мартин Фаулер).

Chaos monkey — это инструмент, созданный в Netflix. Он позволяет выключать серверы для проверки устойчивости системы к такому типу отказов (Мартин Фаулер).

Ребекка Парсонс считает очень важным, что мы больше не используем даже внутрипроцессное взаимодействие между сервисами, вместо этого для связи мы прибегаем к HTTP, который и близко не бывает столь же надёжен. В результате будут возникать сбои при общении сервисов друг с другом, и система должна быть к этому готова.

Архитектура с эволюционным развитием


Архитектура всего приложения не должна быть статичной, необходима возможность её простого развития в соответствии с потребностями бизнеса. Например, можно:

  • Превратить (рефакторить) единое приложение в приложение микросервисное, изолировав и перенеся наборы бизнес-логики (ограниченные контексты) в отдельные микросервисы.
  • Объединить существующие микросервисы, например когда часто приходится одновременно изменять разные микросервисы.
  • Разделить существующие микросервисы, когда нужно и есть возможность развивать их по отдельности или когда мы понимаем, что разделение серьёзно повлияет на бизнес-логику.
  • Временно добавить в приложение какую-то возможность, создав микросервис, который будет работать определённое время.

Фронтенд/бэкенд


Есть два подхода к структурированию фронтенда и бэкенда при микросервисной архитектуре:

  1. Раскидать все части пользовательского интерфейса по микросервисам и сохранять взаимосвязи между соответствующими микросервисами. Это позволяет наладить внутрипроцессное взаимодействие между фронтендом и бэкендом. Но тогда будет очень сложно, если вообще возможно, поддерживать связность UI. В случае перекрёстных изменений границ в UI нам придётся одновременно обновлять несколько микросервисов, создавая взаимосвязи и нарушая изолированность и независимость микросервисов, обеспечиваемые самой архитектурой. Получается практически антипаттерн!
  2. Раскидать кодовые базы фронтенда и бэкенда, оставив UI приложения одним целым, чтобы они потом взаимодействовали по HTTP. Микросервисы будут отделены друг от друга, что дополнительно разделит фронтенд и бэкенд. Зато UI можно поддерживать целиком, легко сохраняя его связность. Такую структуру рекомендует использовать Рейчел Майерс, и, насколько я понимаю, это единственный способ. В таком случае у нас есть два варианта взаимодействия между фронтендом и бэкендом:
    1. Много маленьких асинхронных HTTP-запросов вместо одного большого, что исключит возможность блокировки (этот подход предпочитает Чед Фаулер).
    2. Один большой запрос к специализированным сервисам (шлюзу/агрегатору/кешу), которые собирают данные со всей микросервисной экосистемы. Это уменьшает сложность 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
Mail.Ru Group 789,47
Строим Интернет
Поделиться публикацией
Комментарии 266
  • +5
    К сожалению, у меня нет опыта работы с микросервисами
    Опыт бы не помешал, особенно суппорта, статья получилась бы несколько другой.
    • +17
      Ну почему все время за преимущества выдают какую-то, мягко выражаясь, хрень?

      >У микросервисов доступность выше: даже если один из них сбоит, это не приводит к сбою всего приложения.

      Да-а-а? Представим себе что это микросервис авторизации. Что, скажете нет, это не микросервис? Или его неработоспособность не отразится на работе всего приложения? Ха три раза.

      Тщательнее надо формулировать, тщательнее.
      • +1
        это не обязательно приводит к сбою всего приложения

        fixed

        • +3
          И наоборот, если у меня один модуль (функция) сбоит, то это не значит, что оно приведет к сбою всего монолита. Тогда в каком месте у микросервисов тут выше доступность?
          • +1
            Я бы на самом деле сформулировал бы как-то так — микросервисы должны позволять избавиться от single point of failure. Путем например легкого и быстрого параллельного развертывания нескольких копий. А сами по себе они точно также могут быть этой SPOF, как и модуль в монолитном приложении. Ни больше, ни меньше.

            Т.е., не большая доступность, а простота обеспечения этой доступности, путем применения таких-то решений.
            • +7

              А что мешает развернуть несколько копий монолита?

              • +1
                Ну, несколько копий монолита вероятно сожрут несколько больше ресурсов. А так ничего не мешает.

                Имелось в виду, что в монолите не все является той самой точкой отказа, которую вообще стоит дублировать. Вынести эти части, сделать их автономными, и задублировать (заодно повысить производительность) — это вполне себе годная стратегия.
                • +6

                  Не очень понял вас.


                  1. Допустим в микросервисах есть точка отказа. Мы дублируем микросервис с этой точкой — профит.
                  2. Допустим в монолите есть точка отказа. Мы дублируем монолит — профит.
                    В чем разница?
                  • +5
                    Что тут понимать? Монолит жрет 16Gb памяти. Микросервис, который точка отказа — 128Mb. Дублируем монолит — 32Gb потребности, дублируем микросервис — 16Gb + 128Mb*2. Все числа только как пример.
                    • 0

                      Теперь понятно.
                      Однако хочу заметить что это не повышение производительности (скорее наоборот из за накладных расходов на сетевое взаимодействие), а снижение потребления памяти.

                      • 0
                        А я разве обещал производительность?

                        Скорее это просто снижение накладных расходов на деплоймент (хотя если посчитать в сумме — то возможно окажется, что на развертывание сотни микросервисов уйдет намного больше ресурсов, чем на один монолит). Просто эти ресурсы — их можно будет проще горизонтально масштабировать.

                        Ну и да, сетевое взаимодействие вместо вызовов внутри процесса — это всегда минус микросервисам, без вопросов.
                        • 0
                          Ну и да, сетевое взаимодействие вместо вызовов внутри процесса — это всегда минус микросервисам, без вопросов.

                          Не сетевое, а межпроцессное. Микросервисы и сервисы вообще не обязаны общаться по сети, вполне могут использовать файловые сокеты, разделяемую память и т. п., хотя это накладывает ограничения на инфраструктуру.
                          • 0
                            Нет, не обязаны — но сплошь и рядом используется REST, JSON и т.п. — потому что это дает дополнительную гибкость, если угодно, особенно если вы хотите клиента на разных языках (а вы как правило хотите этого часто, почему нет?).

                            Так что насчет «всегда» — да, я выразился слишком сильно, но как правило взаимодействие все-таки требует дополнительных накладных расходов.
                            • 0
                              Требует, да, по определению сервиса как отдельного процесса или группы процессов. Но какое это будет взаимодействие сами принципы не диктуют.
                              • 0
                                А могут использовать MQ и тогда почти не будет разницы, где расположены сервисы.
                                В одном процессе, в разных, или на разных серверах.
                                Это забота шины взаимодействия.
                                • +1
                                  смысловой не будет, а вот физическая будет
                                  расходы на rpc никуда не денутся

                                  вспоминается реклама Инферно как там всё просто так как есть только файлы.

                                  с тем же успехом можно COM использовать — даже проще будет
                        • +1
                          Монолит жрет 16Gb памяти. Микросервис, который точка отказа — 128Mb.

                          Это что ж Вы такое делаете? Обычно 500 Mb под инстанс монолита более, чем хватает.
                          Хоть числа и только как пример, но их соотношение вызывает вопросы… На микросервис конечно меньше памяти приходится, но во-первых не в 100 с лишним раз, а раз в 5-10, да и сумма памяти, потребляемой всеми микросервисами скорее всего будет в пару раз больше, чем нужно монолиту.

                          • 0
                            >Это что ж Вы такое делаете?

                            То, что написано в ТЗ, а что?

                            >Обычно 500 Mb под инстанс монолита более, чем хватает.

                            Вот прямо так, без понимания того, какие задачи решаются? Хм.
                            • –3

                              У Вас, видимо, есть несколько примеров веб-приложений, которые могут по делу откушать 16 Gb оперативки?

                              • +2
                                Web приложений? С чего вы взяли, что обсуждаемые микросервисы каким-то боком специфичны для веба? И тем более — что монолитные приложения ограничены им?
                                • –3

                                  В статье только аббревиатура HTTP встречается 6 раз, не считая множества других признаков… Так что уместнее вопрос, с чего Вы взяли, что тут обсуждается что-то кроме веб-приложений?

                                  • +1
                                    Видите ли, я вот видел массу приложений, где http налево и направо — просто потому, что SOAP это обычно через http. Но они ни разу не являются веб-приложениями.

                                    И мы тут, между прочим, corba обсуждали. Она видимо тоже веб.

                                    А заодно, кстати, видел веб-приложения, которые совершенно по делу жрут 32 гигабайта и более — самый яркий пример это пожалуй IBM BPM. Всего-то на 50 пользователей, примерно.
                                    • –2

                                      В классических клиент-серверных приложениях все эти микросервисы 10 лет назад уже были, может ещё и раньше были… чего тут обсуждать то? Или Вы их теперь через Docker стали разворачивать? xD


                                      видел веб-приложения, которые совершенно по делу жрут 32 гигабайта и более — самый яркий пример это пожалуй IBM BPM. Всего-то на 50 пользователей, примерно.

                                      Судя по описанию, какая-то web-IDE для описания бизнес-процессов. Хз как она умудряется столько памяти жрать… Интерфейс весь (сохранение взаимного расположения, drag-n-drop, etc.) можно на клиенте отрабатывать, к серверу запросы только при явном сохранении или авто-сохранение раз в минуту, плюс подгрузка запрашиваемых данных в JSON.
                                      Я даже демо-видео посмотрел ради интереса и в упор не вижу с чего бы воркеру этой штуки хотя бы 1 Gb по делу съесть, не то что 32. Просто это IBM и им наплевать сколько вам придётся памяти докупить xD

                                      • –2

                                        Кстати, посмотрел требования к IBM BPM Advanced 8.5.7


                                        For 64-bit systems, the minimum system memory requirement to support a clustered configuration with a deployment manager, node agent, and single cluster member is 6 GB. However, for optimal performance the recommended configuration is 8 GB.

                                        Даже исходя из этого, можно сделать вывод, что у вас скорее был какой-то баг с утечкой памяти...

                                        • +2
                                          Не описания, а описания и выполнения. И да, процессы тоже жрут память.

                                          Намекаю: если вы чего-то в жизни не видели, это не значит, что этого не бывает.

                                          Если в рекомендациях у IBM что-то написано — это не значит, что этому нужно верить.

                                          И нет, не было у нас утечки памяти — мы вполне способны это проверить, и проверяли. Не надо додумывать за других, особенно в областях, где вы соизволили посмотреть демо-видео…
                                          • –1

                                            Ох, как Вас бомбит, даже ссылку на официальные system requirements заминусовали… ну и ну.


                                            Не описания, а описания и выполнения. И да, процессы тоже жрут память.

                                            Ну, если у них бизнес-процессы выполняются в том же процессе, что и IDE, то это не монолит виноват, это уже фантасмагория какая-то.


                                            Намекаю: если вы чего-то в жизни не видели, это не значит, что этого не бывает.

                                            А я и не спорю, что бывает. Но когда такое бывает, всегда можно улучшить и привести систему в более адекватное состояние, было бы желание и ресурсы.


                                            Если в рекомендациях у IBM что-то написано — это не значит, что этому нужно верить.

                                            Вот как! То есть Вы считаете, что когда разработчик заявляет, что для оптимальной работы его системы требуется N памяти (где N — это дофига Gb), а по факту система потребляет 4*N, то это адекватная работа системы? IBM слишком высокомерна по отношению к своим пользователям, примерно как Вы — к собеседникам )

                                            • +1
                                              Вы начали с самого начала делать выводы, исходя их взятых сугубо с потолка чисел, которые были просто примером. При этом я вам сразу сказал — вы пытаетесь что-то додумать, ничего не зная про требования. Т.е. вообще ничего.

                                              И продолжаете это дальше — вы ничего не знаете про приведенную мной в пример систему, но при этом считаете, что она не может потреблять столько памяти. Продолжайте дальше — только без меня.
                                  • 0

                                    Есть еще одна проблема. Даже условно нелсложные веб-приложения со временем обрастают "инфраструктурой". Нужно поставить супервизор для воркеров. Нужно ставить всякие специфичные екстеншены/приложения для обработки юзерских аватаров, парсинга больших прайсов от поставщиков и 100500 прочих вещей которые нуны монолиту. И тут приходит час Ч, когда вы решили замасштабироваться горизонтально. Вы покупаете еще один сервер и начинаете на него сетапать все вот это добро, которым годами обрастало ваше монолитное приложение. Может у вас парсер прайса запускается раз в месяц, но его надо ставить. Может картинки у вас ресайзятя раз в год, но будь-добр ставь. Микросервисы за счет того что фокусируются на чемто одном требуют при масштабировании только необходимую инфраструктуру. И это безусловно плюс.

                                    • 0

                                      Как правило, всё это добро сводится к запуску фоновых задач посредством того же монолита. Поэтому его сетап сводится к переносу crontab, если само приложение его не заполняет автоматически.
                                      А если парсер прайса и ресайзер картинок — это отдельные приложения, то это уже и не монолит по сути.

                                    • 0
                                      По мегабайту на пользователя нормально? А пользователей может быть 16 000.
                                      • 0

                                        Нет, если потребляемое ОЗУ растёт линейно от кол-ва пользователей, то это нормально только для какого-нибудь кеша или in-memory БД, но там есть свои приёмы, чтобы ограничить потребляемую память сверху.
                                        А для основного приложения — это совсем ненормально… Какой-нибудь reddit-эффект и у вас серваки вылетят с out of memory?

                                        • 0

                                          ну если балансер всех 16к одновременных реквестов на одну ноду пустит, то так и будет))

                                          • 0

                                            Под одновременными реквестами Вы имеете в виду в секунду или в минуту? Вообще, когда говорят про пользователей, обычно подразумевается, что в предыдущие N минут были какие-то запросы от 16 тыс. уников. Где N — время, исходя из которого границы визита определяются, для GA и Метрики — это 30 минут iirc. Напрямую rps из этого вывести сложно, не зная специфики приложения.

                                          • 0
                                            Линейный рост потребляемого ОЗУ это норма, а часто идеал, которого не могут достигнуть. А под одновременными запросами имеются в виду не в секунду или в минуту, а именно одновременно обрабатываемые. Грубо, если запрос пользователя обрабатывается 100 мс, то 16000 одновременных пользователей означает 160000 запросов в секунду — в каждый момент времени обрабатывается 16 000 запросов.

                                            А начнут серваки вылетать, ставить запросы в очередь или ещё как разумно реагировать зависит от архитектуры.
                                            • 0
                                              Линейный рост потребляемого ОЗУ это норма, а часто идеал, которого не могут достигнуть.

                                              Т.е. у Вас по графику потребления ОЗУ на сервере можно сразу видеть, где были пиковые нагрузки? Ни CPU, ни Network I/O, а именно ОЗУ?


                                              Грубо, если запрос пользователя обрабатывается 100 мс, то 16000 одновременных пользователей означает 160000 запросов в секунду — в каждый момент времени обрабатывается 16 000 запросов.

                                              Такое количество запросов (популярность на уровне Twitter) никто в здравом уме не будет одним инстансом обрабатывать, т.е. как-то мимо начального вопроса получилось. На всю ферму серверов и 256 Gb нормально будет, а вот 16 Gb на один инстанс (а инстансов и на одном сервере может быть много) всё равно дичь получается.

                                              • 0
                                                Т.е. у Вас по графику потребления ОЗУ на сервере можно сразу видеть, где были пиковые нагрузки? Ни CPU, ни Network I/O, а именно ОЗУ?

                                                И по ОЗУ тоже, собственно обычно все эти графики хорошо коррелируют между собой. Обработка одного запроса требует и ОЗУ, и CPU, и I/O.

                                                а вот 16 Gb на один инстанс (а инстансов и на одном сервере может быть много) всё равно дичь получается.

                                                Пускай будет 1000 мс и 10 мегабайт на запрос — 16 гигов кончатся менее чем на 1600 пользователях по факту.
                                                • 0

                                                  Я не понимаю, почему у Вас каждый запрос обязательно добавляет N мегабайт…
                                                  Возможно, у Вас какие-то очень специфичные задачи… У меня график занятого ОЗУ в течении дня обычно больше похож на горизонтальную линию, при том, что максимальная нагрузка в 20 с лишним раз больше минимальной.

                                                  • 0
                                                    Занимает память, чтобы развернуть граф объектов узлов так на пяток тысяч, выполняет операцию, освобождает память и сборщик мусора отдаёт её системе.
                                        • 0

                                          Пережатие видео и картинок, загружаемых пользователями, например.

                                          • 0

                                            Да, я думал про такой вариант, но отбросил его, т.к. делать это на уровне своего приложения нелогично, когда уже есть ffmpeg, imagemagick и т.д.
                                            Вопрос же был не в общем кол-ве занятой памяти на сервере, а исключительно про занятую под монолитное приложение.

                                            • 0
                                              когда уже есть ffmpeg, imagemagick

                                              Которое ваше приложение будет использовать как микросервисы :)
                                              • 0
                                                Которые не выделываются и просто называются «библиотеками» и «приложениями».

                                                Вы загоняете себя в ловушку терминологий.
                                                Если динамическая библиотека или консольная тулза является микросервисом, то все стоны из монитора — пустая трата времени и сил. Все и так стараются делать модульные приложения там, где это даёт прирост, и ни один здравомыслящий человек не будет агитировать радикально против модульных систем.
                                                В противном случае понятие «микросервисы» как самостоятельный термин обретает смысл. Но этот смысл — радикальная форма модульности, которая применима к узкому числу задач разработки высоконагруженных систем. За их пределами польза от радикалов очень сомнительна.
                                                • 0
                                                  Динамическая библиотека не является — она действует в рамках одного процесса с приложением. (Микро)сервис является отдельным приложением, работающим в отдельном процессе, к которому основное приложение обращается средствами IPC. Традиционно в выражении «используем микросервис» имеется в виду «пользуемся средствами RPC для взаимодействия», то есть средствами удаленной коммуникацией, даже если приложение и сервис работают на одной логической машине, но это не обязательно.
                                                  • +1
                                                    В этом случае ваш предыдущий комментарий. как и многие другие в этой теме, в общем случае не верен. Так как тот же самый ffmpeg не обязательно используется в качестве микросервиса, а может быть включён в приложение в качестве динамической библиотеки. Что выводит приложение из категории «монолит», не приводит в категорию «микросервисов» и позволяет максимально гибко контролировать соотношение скорость/масштабируемость и связность/распределённость.

                                                    И, кстати, выводит практически все программы из категории «монолит», ибо очень сложно найти приложение уровня пользователя, которое вообще не использует библиотеки операционной системы, на которой оно запущено.
                                                    • 0
                                                      Использование ffmpeg или системных библиотек как подключаемых не выводит приложение из монолитов. Вызовы API ОС в теории выводят, но всё же монолитом считают приложение, которое обращается только к ОС, но не к другим приложениям напрямую или через средства ОС. Есть приложения, которые ОС (или вообще биосом, а то и при страте процессора) только запускаются, а потом работают полностью автономно, но это уже какие-то супермонолиты. Считать их обычными монолитами, значит на большинстве практических задач исключить монолиты из рассмотрения вообще, подавляющее большинство систем не будут считаться монолитными.
                                                      • –1
                                                        Выводит или не выводит — это очень дискуссионный вопрос. Взгляните на это не со стороны «единой программной памяти» (которой нет, у каждой библиотеки своя куча), а со стороны гибкости масштабирования приложения. Динамическая библиотека может быть загружена и выгружена на лету, средствами ОС (как и микросервисы), и может реализовывать как сам функционал, так и работу с микросервисами. То есть правильно построенный модульный проект может быть скомпанован в очень компактный альтруистичный дистрибутив, а может быть разделён на сеть микросервисов. И я бы не сказал, что это особо сложнее, чем просто микросервисная архитектура.
                                                        Конечно, тут же можно возразить, что это уже не монолитная архитектура, но, во-первых, вы уже написали «Использование ffmpeg или системных библиотек как подключаемых не выводит приложение из монолитов.», а во-вторых, динамические библиотеки с минимальными усилиями можно* превратить в статические (больше всего возни с глобальными объектами, которые не шарятся между модулями), а те собрать в единое неделимое приложение.
                                                        *Есть исключения.

                                                        Подытожу, я не говорю, что микросервисная архитектура — это плохо, она позволяет легко и быстро производить горизонтальное масштабирование. Но она НЕ серебряная пуля, и НЕ даёт преимуществ над правильно организованным модульным приложением в тех случаях, когда горизонтальное масштабирование не требуется. Напротив, оно вводит как ряд ограничений, вроде используемых протоколов взаимодействия и полного разнесения данных, так и ряд накладных расходов, в виде медленных внутренних сокетов (по сравнению с общей памятью и стеком).

                                                        Если мы говорим, что «монолит» — синоним «модульного», у меня для вас плохие вести.
                                                • +1
                                                  Которое ваше приложение будет использовать как микросервисы :)

                                                  Какая-то ложная дихотомия получается… Этак, если в проекте используется cron, то он уже микросервисным резко становится? xD

                                                  • 0
                                                    Если приложение обращается к крону в качестве планировщика (обычно наоборот, крон обращается к приложению), то да. По сути крон есть микросервис планирования запуска задач. Впрочем как и большинство никсовых инструментов.
                                                    • 0

                                                      "Резко" микросервисным не становится. Смотря что крон запускает. Если какую-то часть приложения, то приложение уже не монолит.

                                                      • 0
                                                        Тут зависит больш ене от того, что крон запускает, а о того кто кронтабы формирует.
                                                        • 0

                                                          Да, я имел в виду случай, когда кронтаб формируется приложением, для вызова самого себя с определенными параметрами в определенное время.

                                  • 0
                                    Рискну: экономическая составляющая = рентабельность = стоимость?
                                    • 0

                                      Это довольно общие понятия. Можете пояснить конкретнее?

                                      • 0
                                        Имелось ввиду что это попросту может быть дорого.
                              • 0

                                Дополню ваш комментарий Ссылка статьей

                                с разоблачением мифов относительно микросервисов.
                                • 0
                                  Да-а-а? Представим себе что это микросервис авторизации.

                                  Будет работать публичная часть приложения. У вас это только форма аутентификации? Но ведь будет работать!
                                  • 0
                                    А почему она в монолитном приложении не будет работать? Форма будет открываться, точно также.
                                    • 0
                                      Потому что приложение работать не будет.
                                      • +6
                                        Почему это приложение работать не будет? все будет работать кроме формы аутентификации.
                                        • –1

                                          Наверное, имеются в виду отказы, приводящие к падению/недоступности приложения.


                                          В одном случае упадет/недоступен только микросервис, в другом — весь монолит. Как то так.

                                    • +2
                                      Так и с монолитом также, не будет работать авторизация, а все остальное будет.
                                      • –4
                                        Монолит на то и монолит, что он или работает, или нет. Грубо, или слушает 80-й порт, или не слушает.
                                        • +2
                                          Может один endpoint(controller/action) не работать, а все остальные вполне могут работать.
                                          • –2

                                            Скажем в случае PHP, так и будет. А в случае компилируемых приложений, один раз упав приложение уже само не поднимется и станет недоступно по всех ендпойнтах.

                                            • +2

                                              Само не поднимется, но система может перезагрузить упавшее приложение.

                                              • –1

                                                Это все понятно, но это уже внешнее по отношению к приложению. Микросервисы же не тянут за собой подобной проблемы. Если микросервис упал, то остальные всеравно работают независимо от технологий, на которых они созданы.
                                                зы. За что минус не пойму, аргументируйте чтоли

                                                • 0

                                                  Начнем с того, что в зависимости от предметной области могут быть связи между микросервисами. И пока ключевой сервис не поднимется, то остальные сервисы будут ждать и ничего не делать. Независимо от монолит или мокросервисы, восстановление и отказоустойчивость это отдельная тема.


                                                  Так же в зависимости от предметной области, некоторые сервисы легко масштабировать, а другие почти невозможно.

                                                  • 0
                                                    Начнем с того, что в зависимости от предметной области могут быть связи между микросервисами.

                                                    Самое сложное в написании микросервисов — это определние границ этих микросервисов. Как уже писали в комментах, микросервис должен быть слабо связан с другими. Если этого достичь нельзя, то микросервисная архитектура не подходит для вашего приложения, вот и все. Не микросервисы плохие, просто они не подходят в данном конкретном случае.

                                                  • 0
                                                    За что минус не пойму, аргументируйте чтоли


                                                    Не ставил минус, но, видимо за это:

                                                    Скажем в случае PHP, так и будет. А в случае компилируемых приложений, один раз упав приложение уже само не поднимется и станет недоступно по всех ендпойнтах.


                                                    Автоподъем сервисов реализуется нынче в любом продакшене. Хоть с микросервисами, хоть с крупносервисами.
                                                    • 0
                                                      Средствами самого приложения?
                                                      • 0

                                                        Да, так тоже делают. Скажем, если в том же C# не использовать небезопасного кода, то довольно хорошо отрабатывает монитор в отдельном appdomain.


                                                        А можно эту задачу поручить и системе. Так, винда умеет перезапускать службы автоматически. В линуксе есть специальные обертки, которые занимаются перезапуском.

                                                        • 0
                                                          Средствами самого приложения?


                                                          Иногда. Чаще внешними средствами.

                                                          Такое впечатление, что вы в глаза не видели микросервисы, если считаете, что оно там как-то само поднимается.

                                                          Отнюдь не сами микросервисы себя восстанавливают. Микросервисы роутятся на резервные в случае аварии и поднимаются внешними средствами по отношению к микросервисам.

                                                          С крупносервисами — также. Но иногда в них реализован и автоподъем. Для микросервисов такого не делается, так как микросервис — это управляемый извне маленький винтик большого механизма.

                                                          Если интересно — см. Kubernetes — это сейчас один из самых развитых инструментов для управления микросервисами.
                                                          • –1
                                                            Такое впечетление что вы не читаете, но сразу бежите осуждать.

                                                            Речь шла о том, что если упадет монолит, то пока его не понимут (админы, системные утилиты, верховные силы) он будет лежать. И будет лежать весь полностью.

                                                            В случае монолита на пхп (как пример), это чуть менее критично, помтоу что каждый запрос стартует приложение по новому и лежать будет только то, что сломано, остальное вполне еще может работать.

                                                            В случае микросервисов (независимо от технологий), если падает микросервис, то остальное приложение будет функционировать (естественно зависит от степени критичности упавшего микросервиса)
                                                            • +1
                                                              В случае микросервисов (независимо от технологий), если падает микросервис, то остальное приложение будет функционировать (естественно зависит от степени критичности упавшего микросервиса)


                                                              Не все так просто.

                                                              1. Все до единого микросервисы поднимаются довольно долго. В сумме это заметно дольше, чем один монолит.

                                                              2. Монолит никто не мешает делать как минимум дублем — оригинал и реплика. Даже 2 реплики — сейчас сие стандарт для серьезных систем.
                                                              • 0
                                                                1. Ну это должен быть просто какойто колосальный косяк, чтобы все до единого микросервисы содержали ошибку и одновременно упали. Обычно падает один, растет очередь не обработанных событий, накрывается брокер, падает все. Но до момента падет все есть достаточно времени, чтобы откатиться на предыдущую стабильную версию и поднять один упавший микросервис, пока не упало все.

                                                                2. Конечно, можно запустить дубли монолита, если в релиз ветку пролез баг, то упадут все дубли монолита, а не все дубли одного из многих микрсоервисов
                                                                • 0
                                                                  А вы не пишите так, чтобы монолит падал целиком.
                                                                  Современные языки программирования и инструменты тестирования облегчили вам задачу в последние годы более чем.

                                                                  Когда монолит отказывается выполнять какую отдельную функцию и это вызывает возврат сообщения об ошибке — сие совершенно нормально и совершенно аналогично микросервисной архитектуре.

                                                                  Вы не там ищете преимущества микросервисов.

                                                                  Их преимущества в возможности горизонтального масштабирования, которая недоступна монолиту.

                                                                  И за эти преимущества приходится платить менее оперативным перезапуском именно системы микросервисов и задержками в их связанностях. У монолитов все проще и быстрее.
                                                                  • 0
                                                                    угу, проще и быстрей. Есть опыт деплоя монолита на продакшен ~ 3 часов.
                                                                    • +1
                                                                      угу, проще и быстрей. Есть опыт деплоя монолита на продакшен ~ 3 часов.


                                                                      Компилировали новую, предварительно опустив старую версию???
                                                                      • 0
                                                                        Или это был recover аварийно прерванных транзакций?

                                                                        Уверяю вас, проблем при старте микросервисов, по причине более сложной их связанности — намного больше.
                                                                        • 0
                                                                          В основном синк файлов на 2 дц.
                                                                          • +1
                                                                            В основном синк файлов на 2 дц


                                                                            И каким боком это проблема монолита?
                                                                            • 0

                                                                              Синк файлов на 2 дц можно делать в том время, когда старая версия еще работает.

                                                        • –1
                                                          Пока перезагружает всё приложение работать не будет :) Давайте только не углубляться, что у приложения несколько воркеров и запрос на конкретный ендпоинт будет ложить только один воркер, а остальные продолжат работать.
                                                        • 0
                                                          Откройте для себя, например, Java и Spring, прежде чем утверждать подобное.
                                                        • –1
                                                          Вы не путаете «не работать» и «работать не корректно (на корректные запросы возвращать ошибку, например)»? Я говорю о ситуации «не работает» — API не доступен клиенту, отправляет запрос и или вообще не получает ответа, или получает ответ от инфраструктуры (сетевого стека ОС, например) «получатель не найден», «не могу установить соединение», «получатель разорвал соединение» и т. п. Не, может быть, конечно, несколько ендпоинтов, например основное приложение на 80 порту, а авторизация на 443 (защищаем только пароль/ключ клиента, а сессионный токен — нет) и 443 не работает (приложение при старте проигнорировало, что не смогло забиндить), но обычно всё же один делают.

                                                • 0

                                                  del

                                                  • +5
                                                    Микросервисы позволяют по мере необходимости обновлять приложение по частям. При единой архитектуре нам приходится заново развёртывать приложение целиком, что влечёт за собой куда больше рисков.

                                                    А разве развертывание по частям не несет риски нарушения Согласованности (Consistency)?

                                                    • +13

                                                      А почему никто не пишет, что при разделении монолита тотально падает время отклика системы? Вызов, который ранее случался через стек за несколько тактов теперь передается аж по сети, да еще с сериализацией в текст (http же).


                                                      Также возможность горизонтально масштабировать случается в ущерб возможности вертикально.

                                                      • 0

                                                        Согласен. Замолчали о важном факте.
                                                        Я считаю это необходимо добавить в минусы микросервисов.

                                                        • 0
                                                          Это от архитектуры зависит. Время отклика может и уменьшаться при введении микросервисов. Грубо, раньше клиент делал один запрос к монолиту, который последовательно собирал данные из десятка слабосвязанных запросов по пятку таблиц в каждом, а теперь клиент делает десять запросов к сервисам одновременно, получая конечный результат раньше.
                                                          • +7

                                                            Это означает только то что монолит был написан коряво. Если архитектура и бизнес-процесс позволяют из хранилища получать данные параллельно, то и монолит и микросервис могут их получать параллельно.

                                                            • –2
                                                              У микросервисов у каждого свое хранилище, они не конкурируют, а у монолита одно хранилище как правило, а если их несколько и с каждым работает независимая часть монолита, то это уже не монолит получается :)
                                                            • +3
                                                              Стоп, стоп. Вот не надо считать разработчиков монолита идиотами априори! )))

                                                              Если десять запросов можно сделать асинхронно — они и в монолите могут быть сделаны асинхронно — это не преимущество микросервисов.
                                                              • –3
                                                                Преимущество микросервисов — у каждого свое хранилище, запросы к ним не конкурируют.
                                                                • +7
                                                                  Точно также и в монолите, есть сервисы(не микро) и они делают запросы к разным хранилищам.
                                                                  • –1
                                                                    Именно. Совершенно не понял, почему это я не могу сделать даже в рамках одной базы несколько файловых групп, размещенных на разных физических дисках, которые не конкурируют друг с другом за IOPs? Это делалось много лет назад, и делается.

                                                                    А вот представить себе сто отдельных оракловых серверов вместо ста баз на одном физическом сервере мне как раз будет сложно — потому что это создаст лишние немалые расходы на их поддержку.
                                                                    • 0
                                                                      Конкурентность имелась в виду прежде всего транзакционная, а не за физические ресурсы.
                                                                      • +3
                                                                        Параллельное выполнение транзакций вполне себе решается в рамках баз данных уже много лет как. Микросервисы тут ничего нового ровным счетом не дают. Еще раз — не надо представлять себе монолит как скажем один класс из 100000 строк. Такого не бывает. Даже в самом монолитном приложении есть модули, которые все равно независимы друг от друга. Иногда даже могут быть отдельно перезапущены. Это было возможно до того, как вообще появилось слово микросервис.
                                                                    • –2
                                                                      Микросервис — разновидность сервисов. Если приложение разбито на сервисы, то оно уже не монолитно, а микро сервисы или «макро» — уже нюанс.
                                                                      • +2
                                                                        Нюанс в том, что не разбитых на части приложений уже лет 30-40 как не делают вообще. Оно может быть монолитом в том смысле, что деплоится целиком — но при этом вполне состоять из частей. У него один общий файл конфигурации — но оно все равно состоит из ядра и плагинов.
                                                                        • 0

                                                                          Вот именно! Почему-то многие проводит дихотомию "микросервисы — монолит", забывая об остальных вариантах архитектуры. И выдают за достоинства микросервисов любые недостатки монолита.

                                                                          • 0
                                                                            Т.е. монолит это когда весь код приложения только в одной функции?
                                                                            • –1
                                                                              Грубо, когда весь код исполняется в одном процессе.
                                                                    • 0
                                                                      А что в монолите невозможно вызвать функцию асинхронно?
                                                                    • 0
                                                                      Это только в том сферической случае, когда монолит был разнесён по микосервисам из точно того же кода, плюс у вас мгновенная скорость ответа от сервера клиенту.

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

                                                                      Насчёт сериализации в текст — вот вообще не понял. Если у вас были бинарные данные, они точно так же и останутся бинарными. Если нет, то там тот же незначительный оверхед.
                                                                    • +1
                                                                      Все еще не понимаю почему SOA и микросервисы идут параллельно? Кто-то считает их чем-то отдельным, другие ближе к истине и считают микросервисы подмножеством SOA, но на самом-то деле это одно и то же ведь. Где грань находится?
                                                                      • +3
                                                                        Да нет ее, этой грани. Знаете, мне как-то попался «рекламный» документ, о том, как мы будем внедрять микросервисы у себя в компании. Я его читаю, и вижу, что в нашем приложении, которое Java и OSGI, уже давно все микросервисы.

                                                                        Вспоминаю, что было лет 10 назад — и понимаю, что EJB beans тоже были в значительной степени микросервисами. И те, и другие, не деплоятся сами по себе куда-то, а работают в контейнере — но это дает свои преимущества, скажем в плане мониторинга.

                                                                        То есть, самой подобной архитектуре — ей сто лет в обед. Можно еще corba вспомнить, например. Скока это лет назад?

                                                                        А дальше все зависит от того, где вы проведете границы между сервисами — может получиться хорошо, а может и не очень. Принципы — практически теже самые, что применяются «в малом» — сервис должен быть сильно связан внутри, и слабо снаружи. Так это верно для любого модуля, и это все знают.
                                                                        • +1

                                                                          Вот именно.
                                                                          Отсюда возникает логичный вопрос: откуда такая шумиха?

                                                                          • +3
                                                                            Сам бы хотел это знать :). Но вообще есть одно предположение — произошло некоторое развитие средств виртуализации, и стало очень просто задеплоить еще одну виртуалку с готовым к работе linux, или docker контейнер, где уже развернута база данных или apache, или что-то еще подобное. В мире Java это случилось лет 10 назад, в виде EJB или OSGI, и поэтому там микросервисы уже давно достарочно типичны. А щас стало возможно развернуть что угодно, одним пинком. Шумиха может и несколько излишняя, но какой-то смысл во всем этом несомненно есть.
                                                                            • 0

                                                                              Появились средства контейнеризации, облака — и достали из закромов старый прием и назвали по-новому.

                                                                              • +3
                                                                                Фигня. Это всё было и раньше, просто мы не знали, что оно называется именно так. Взгляните внимательно, это же агрессивный маркетинг, евангелистами которого являются говорящие головы крупных компаний. Не известные программисты со своим независимым мнением, а маркетологи компаний, продающих сервера. О чём это по вашему?

                                                                                А по мне очевидно — о деньгах.
                                                                                Ребекка Парсонс считает очень важным, что мы больше не используем даже внутрипроцессное взаимодействие между сервисами, вместо этого для связи мы прибегаем к HTTP, который и близко не бывает столь же надёжен.
                                                                                Спрашивается, ради чего необходимо отказываться от технологии, которая позволяет сэкономить время и ресурсы? Очевидно, деньги. И дело не столько в экономии самих тактов, сколько в создании новых квазипродуктов и захвате рынка у классических инструментов. Что мешает создать генератор API под все платформы и языки над MPI, к примеру? Почему нет? Видимо, потому, что рост рынка будет незначительным, а все деньги уйдут разработчикам MPI.
                                                                            • 0
                                                                              Можно еще corba вспомнить, например. Скока это лет назад?

                                                                              Трепыхается еще родненькая.
                                                                            • 0
                                                                              Не одно, а подмножество. Грань, скорее всего, не в физическом размере, а в бизнес-отвественности. Микросервис имеет одну единственную собственную бизнес-ответственность, хранит данные только для неё, делегируя всё остальное, начиная с аутентификации, другим сервисам, если это вообще необходимо. Микросервисы хорошо ложаться на принципы DDD, на что указано в статье.
                                                                            • 0

                                                                              О преимуществах микросервисов стоит судить не с точки зрения "модули, которые общаються по хттп вместо in-process call, зачем?", а с точки зрения облачного развертывания. Это скорее набор микро-приложений (а не модулей), которые друг с другом взаимодействуют мало и редко.


                                                                              Представьте банковские сервисы: сервис курсов валют запрашивают миллион раз в день, сервис свифт-переводов — тысячу раз. В облаке дешевле отмасштабировать только нагруженный сервис — деплой и контейнер дешевые (бесплатные), плюс автомасштабирование от облачного вендора будет дешевле.

                                                                              • 0

                                                                                Т.е. содержание облака с двумя микросервисами, которые получают 1000000 и 1000 запросов за день будет дешевле содержания облака с двумя монолитами, которые получают 500000 и 500 запросов за день?

                                                                                • 0
                                                                                  У васв облаке сколько угодно инствнсов микросервисов (пропорционально нагрузке), и у вас ровно ресурсов под каждый столько, сколько надо. Монолит же будет есть больше ресурсов, так как он будет готов как к миллиону переводов, так и к миллиону курсов валют, что оверхед.
                                                                                  • +2

                                                                                    Вы утверждаете, что он, при низкой нагрузке, будет жрать больше ресурсов, чем система микросервисов.
                                                                                    "Размазывая" работу монолита по микросервисам вы не уменьшаете общую нагрузку.
                                                                                    Монолит не будет есть больше ресурсов только потому что он монолит.
                                                                                    Монолит потребляет столько же ресурсов, как и микросервисы при одинаковой нагрузке. Просто некоторые части из которых он сложен буду простаивать.
                                                                                    Так что никакого оверхеда нет.

                                                                                    • 0
                                                                                      Разве часть монолита которая простаивает не будет потреблять лишнего?
                                                                                      • +1

                                                                                        А что именно в простаивающем приложении может потреблять ресурсы?
                                                                                        Мне приходит на ум только "лишние" модули/библиотеки загруженные в память. Но это ничтожно мало.

                                                                                        • +1

                                                                                          В случае, если облачный провайдер взимает плату за трафик внутри кластера микросервисов, получается наоборот: монолит жрет меньше

                                                                                        • 0

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

                                                                                        • +2

                                                                                          Если монолит — полный stateless и содержит в себе только обработчики запросов — то разницы нету.
                                                                                          Если монолит содержит в себе какое-то состояние — явное или неявное (кеши, сессии в памяти, восстановленные CQRS агрегаты ), или поведение — задачи по расписанию и т.п. — то разница есть, и значительная.

                                                                                          • 0

                                                                                            А вот тут я с вами соглашусь.
                                                                                            Тем не менее, вы сами даете решения для монолита: stateless, липкие сессии, отдельный инстанс для задач по расписанию, распределенный кэш.
                                                                                            Хотя в этом случае задачи по расписанию можно выделить в отдельный микросервис, ибо ферма монолитов, будучи неправильно настроена, может конфликтовать пытаясь конкурентно выполнять эти задачи.
                                                                                            Получается, что микросервисы, в некоторых случаях, все же лучше чем монолит с состоянием.
                                                                                            Не если сравнивать с монолитом без состояния, увы, опять не вижу преимуществ.

                                                                                      • 0
                                                                                        Считаем, что один инстанс может обработать по CPU/IO 500000 запросов первого типа и требует 100 метров памяти, или 1000 запросов второго типа и требует 500 метров памяти. В случае монолита вам нужно будет два инстанса с 600 метров, чтобы обрабатывать 1000000 и 1000 запросов, причем 500 метров на одном из них будут простаивать, а в случае микросервисов нужно два по 100 и один на 500 и простоев не будет.
                                                                                        • 0
                                                                                          Считаем, что вам нужно не два инстанса по 100 и один 500 метров памяти, и не два по 600, а один на 700. Экономим на процессоре (и всем остальном кроме памяти), электричестве, аренде места в стойке.