company_banner
1 февраля в 18:13

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



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

Содержание



Микросервисная архитектура — это подход к созданию приложения, подразумевающий отказ от единой, монолитной структуры. То есть вместо того чтобы исполнять все ограниченные контексты приложения на сервере с помощью внутрипроцессных взаимодействий, мы используем несколько небольших приложений, каждое из которых соответствует какому-то ограниченному контексту. Причём эти приложения работают на разных серверах и взаимодействуют друг с другом по сети, например посредством 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
Автор: @AloneCoder Herberto Graca
Похожие публикации

Комментарии (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. Экономим на процессоре (и всем остальном кроме памяти), электричестве, аренде места в стойке.
          • 0
            Это нарушение условий, это получается что один инстанс может обработать 1000000 запросов, не упираясь в CPU/IO, хотя и потребует 200 метров памяти. По условиям вертикальное масштабирование уже невозможно практически, только горизонтальное. Монолит мы будем вынуждены масштабировать весь, в сервисах — только узкие места.
  • –1
    Независимая эволюция подсистем
    Микросервис может развиваться и ломать обратную совместимость, не обременяя себя поддержкой старых версий, так как всегда можно оставить старую версию микросервиса работающей необходимое время.

    Монолитное приложение делится на сборки (пакеты, динамические библиотеки).
    Давно существуют технологии их параллельной (side-by-side) установки и выполнения.


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

  • 0
    Пообщался, с народом, которые буржуинов обслуживают.
    Так, вот есть вариант, одни жертвы пропаганды, и пытаются впихнуть Docker везде, что заканчивается печально(в основном по безопасности), ибо администрировать уникальных 100-500 сервисов black-box это еще то занятие, но зато у Google в наличии всегда бесплатные тестировщики.
    Другие используют осознано.
    Пример: ребята занимаются, глубоким анализом данных, им нужно быстро поднять супер кластер, выполнить анализ, и погасить кластер (дабы не переплачивать, за ресурсы) — они продают АНАЛИТИКУ, тем более все мы знаем, что производительность при использовании «контейнеров» в *nix близка к native. На безопасность, им грубо говоря «пофик», обновились раз в пол-года, год и норм. Вот это нормальный «case» для Docker.
    Также, у них имеются, архаичные алгоритмы, использующие еще более архаичные библиотеки(libs), при этом утилизирующие процессор под 100%, кто их и как писал уже никто не знает, кроме того они работают, и не всегда есть время и ресурсы это перекомпилировать, и если архитектура чудным образом совпадает, то тут, Docker, аналогично рулит. Самое главное Docker позволяет, это дело засунуть в кластер масштабировать(но не все так гладко, как на бумаге).
    Вообще Google, не дают покоя лавры java, если он добьется поддержки контейнеров для windows (по факту уже), и начнет перетягивать к себе в облака, завлекая сервисными «плюшками» + организуется инфраструктуру для Docker для домохозяек, где каждый условный расчет, можно будет запустить одной кнопкой на кластере, то вполне себе, конкурент java. Посмотрим, что из этого выйдет.

  • +1
    Пример монолита потребляющего больше ресурсов(как человеческих так и машинных) чем микросервисы:

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

    backend можно разделить на две части — api для frontend-а и обработка видео
    Обработка видео подразумевает, что система должна содержать в себе(а python, как правило. подразумевает и подгрузить) кучу библиотек, а в идеале иметь соответствующее железо

    Фронтенду и бэкенду все это не нужно. Более того, они не должны страдать от бага в коде обработки видео и упасть при импортах.
    При разделении на микросервисы отпадает необходимость оптимизаций и разделений на уровне кода, чтоб ни дай бог, бэкэнд api не попытался проимпортировать что-либо, что потянет за собой импорт, например opencv, которого и в помине нет на серверах api backend

    Допустим баги это уже слишком, они должны выявляться раньше
    Но в плане нагрузки — фронтенд и бэкэнд api нужно развернуть 100 раз, а сервис для обработки видео 10 раз
    Монолит потребует загрузить тот же opencv все 110 раз. Либо быть аккуратней с импортами. А где нужно быть аккуратней — там опять таки баги

    Докер же помогает поддерживать обе среды в постоянном состоянии, легко доступном как разработчикам, так и для деплоя. Отсюда и микросервис-бум. Раньше это было намного сложнее(не путать с невозможно)
    • 0
      Ответьте, с чего вы взяли, что «монолит» — это говнокод, в котором нет ни отлова ошибок, ни обработки исключительных ситуаций, ни, О УЖАС!, разделения на модули, которые можно обновлять по отдельности? Почему монолит — обязательно говнокод?

      Вот вам контрпример, причём сильный. Никсовый bash обладает полным набором всех необходимых любому программисту функций. Большинство никсовых команд — приложения (читай — микросервисы). Иными словами, скрипты баша — одна из первых массовых микросервисных систем. Тем не менее, никто не программирует серьёзных приложений на bash. Все почему-то лезут то на плюсы, то на джаву, то на питон, то ещё куда. Вопрос: почему? И второй вслед: если эта логика справедлива на уровне построения модуля, то почему она перестаёт быть справедливой уровнем выше?

      И под конец, хватит уже нахваливать докер. Это не панацея, а узко специализированная виртуальная машина под никсовые сервера. Которая за пределами своей задачи работает весьма херово.
      • 0
        ни, О УЖАС!, разделения на модули, которые можно обновлять по отдельности?

        Если можно обновлять модули по отдельности без особых рисков — это уже не монолит.

        Иными словами, скрипты баша — одна из первых массовых микросервисных систем.

        Не верно. Скрипты баша — одна из первых массовых систем автоматической оркестрации микросервисов :)

        узко специализированная виртуальная машина под никсовые сервера.

        Не виртуальная машина, а удобный инструмент для управления изоляцией процессов средствами ОС. Докер не изолирует процессы больше чем может сама ОС, вся инфрастуктура докера по сути заточена на то, чтобы было удобно запустить стандартный процесс (ну и взаимодействовать с ним) стандартными средствами ОС, передав им нужные параметры изоляции в легко понятной человеку форме. Какие ещё задачи вы пытаетесь на докер возложить, что он с ними хреново справляется не в никсовом серверном окружении?
        • +1
          Если можно обновлять модули по отдельности без особых рисков — это уже не монолит.
          Но ещё не микросервис.
          Не верно. Скрипты баша — одна из первых массовых систем автоматической оркестрации микросервисов :)
          Хоть груздём назови, только в печку не кидай.
          Какие ещё задачи вы пытаетесь на докер возложить, что он с ними хреново справляется не в никсовом серверном окружении?
          Работать под виндой?.. В целом, докер — вполне себе виртуальная машина. То, что он не эмулирует оборудование, а протаскивает его от хоста — не показатель. Куда интереснее, запустится ли он с отключёнными средствами аппаратной виртуализации аля Intel VT/AMD-V? Я не знаю.
          • +2

            Docker — не ВМ. Это всего лишь удобный консольный интерфейс для запуска программ в ограниченном окружении, используя уже имеющиеся в ядре Linux технологии: capabilities, namespaces, cgroups, veth, aufs, overlayfs, iptables. Плюс эффективное хранение контейнеров в виде «слоёных» ФС и удобство их создания, получения, распространения (Docker Hub). Ещё маркетинг и пиар. Всё.


            запустится ли он с отключёнными средствами аппаратной виртуализации аля Intel VT/AMD-V

            Если у вас запустится свежий Linux (на ядре 3.сколько-то там), то у вас запустится докер. Все эти побрякушки ему не нужны. Процессы в контейнере — это процессы вашей ОС. Просто у них подрезаны capabilities, они засунуты в namespace, на них навешана cgroup, у них свой виртуальный ethernet-адаптер и отдельный chroot на каждый контейнер. Если захотите, то сможете сделать это всё и ручками.

            • 0
              для запуска программ в ограниченном окружении
              Самое интересное что там можно запустить другой дистрибутив (ядро) отличное от хостовой ОС.
              • 0
                Самое интересное что там можно запустить другой дистрибутив (ядро) отличное от хостовой ОС.


                Ключики в конфигурационном файле для другого ядра какие подскажите
              • 0

                Там можно запустить другой дистрибутив — но не ядро.

                • 0
                  Да, вы правы.
              • 0

                Дистрибутив — да, ядро — нет. Процесс в контейнере будет загружать и использовать библиотеки из дистрибутива в контейнере (libc, например), но работать он будет на ядре вашей ОС. Потому что это будет процесс именно вашей ОС, и вы его увидите в списке процессов вашей ОС (top, ps) и у него там будет PID и этот PID будет отличаться от того, что в контейнере (там он будет иметь PID 1, потому что в контейнере не запускается своей ОС).


                Просто попробуйте выполнить uname для разных дистрибутивов:


                ➜  ~ docker run ubuntu:12.04 /bin/uname -a
                Linux 1c89ad5dc611 4.9.6-moby #1 SMP Sat Jan 28 17:18:18 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
                ➜  ~ docker run ubuntu:16.04 /bin/uname -a
                Linux 4ec17fded22d 4.9.6-moby #1 SMP Sat Jan 28 17:18:18 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
                ➜  ~ docker run centos:7 /bin/uname -a
                Linux efba65e848c1 4.9.6-moby #1 SMP Sat Jan 28 17:18:18 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
            • 0
              На никсах — возможно. Я, как виндовый разработчик, могу говорить определённо только про виндовую ветвь. И что-то мне подсказывает, что в ней это всё сделано через виртуальную машину Hyper-V. Не знаю, быть может дело в том, что докер не ставится в отсутствии оной?
              • 0

                На других операционках да — ставится ВМ с Linux и на ней работает Docker. Про Windows не скажу — много лет уж не пользуюсь, но на макоси Docker безбожно тормозит и есть много геморроя с настройкой сети.

              • 0
                В последних релизах виндовс «ядро» линукс реализовано (не до конца, правда) нативно, без виртуализации, просто ещё относительно высокоуровневое API над Kernel API наряду с Win API или как там оно называется. И под виндовс докер запускается, афаик, тремя основными способами: виндовс-докер для виндовс-приложений нативно над Win API, линукс-докер для линукс-приложений в виртуалке, линукс-докер для линукс-приложений нативно над Linuх API.
                • 0
                  Но зачем ему Hyper-V для нативных приложений Windows? Или это от лени, дабы не тратить время на отсталые оси и отсталых разработчиков?
                  • 0
                    Есть Docker под Windows для Linux-приложений от команды докера — он через виртуалку работает, есть поддержка Linux от Microsoft — она нативная :)
  • +1
    Немного вопрос не по теме, но: кто это такой «красивый» на главном фото?
  • 0
    Создайте базовую клиентскую библиотеку HTTP REST, оптимизированную для REST-вызовов, на основе которой можно строить конкретный микросервисный клиент, им будут пользоваться другие микросервисы. Этот оптимизированный клиент должен быть портирован на все языки, применяемые в вашей экосистеме.

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

    Какие-то варианты RPC и(или) MQ в случаях когда большинство сценариев использования выглядит примерно как (в скобках полезная нагрузка):
    — зарегистрировать нового клиента (куча персональных данных)
    — создать (список товаров и их количества) и предоставить ему договор со статусом «черновик»
    — при подписании (просто событие) изменить статус договора на «подписан» и сформировать и предоставить счёт на оплату
    — при оплате (сумма) и её достаточности изменить статус договора на «доставка» и сформировать бухгалтерские проводки и ордер службе доставки
    — … куча событий службы доставки в другом контексте
    — при получении подтверждения о доставке (просто событие) изменить статус договора и ордера на «исполнен», перенести договор их оперативного хранилища в архив, поставить «лайк» менеджеру для системы мотивации
    И это только идеальный сценарий и без получения оперативной и глобальной аналитики

    По сути у нас лишь две операции явно создающие какие-то сущности/ресурсы и куча неявных побочных созданий, изменений и т. п. других сущностей, о которых часто даже информировать инициатора запроса не нужно, просто сообщить ему «ваш запрос принят к обработке», а информировать надо кого-то другого.
  • +7
    OMG, опять «микросервисы — это масштабируемость». Масштабируемость сервиса зависит от того, создали его масштабируемым, или нет.
    • –1
      Микросервисы гораздо легче (в том числе дешевле) масштабируются при прочих равных, если нагрузка на разные функции приложения в целом растёт непропорционально. Грубо, запросы к одной функции приложения стали делать в 10 раз чаще чем к остальным — в случае микросервисов мы отмасштабируем только эту функцию, в случае монолита или «макро»-сервиса будем вынуждены масштабировать и остальные, тратя зря ресурсы.
      • 0
        При правильной архитектуре, можно выдернуть эту функцию из монолита (подменить на «прокси») и сделать микросервисом либо внешней либой (на c/с++, если нужна оптимизация), с минимальными изменениями в монолите. Преимущество в том, что это будет сделано когда будет реальная необходимость.
        • +2

          А там в статье ровно это и написано — если у вас есть новый проект, не делайте его сразу на микросервисах. Но постарайтесь сделать его архитектуру такой, чтобы при необходимости, вы могли выдернуть из него компоненты и преобразовать их в микросервисы. "правильная архитектура" она же из нечего не появляется сама по себе. За ней должна какая-то идея стоять. Вот микросервисы и есть одна из таких идей. Примуществом этой идеи является то, что она достаточно внятно сформулирована.

  • 0
    Микросервисы, как и прочие технологии, не серебрянная пуля. Это все лишь инструмент для решения определенного класса задач.
    Как и с любым инструментом, микросервисы нужно уметь правильно готовить. Не в смысле взял докер, разделил базы, выставил api в виде rest, etc. А в смысле, правильно оцениваешь риски и выгоды, и распределяешь их в оптимальном сочетании.
    При «умелом подходе» на микросервисах запросто можно сваять известную коричневую органическую массу.
    Точно так же как и при использовании монолита.

    Верно и обратное, с головой можно качественно ваять и на микросервисах, и на монолите.

    Главное преимущество микросервисов перед монолитами — собственно говоря почему про микросервисы говорят из каждой кофеварки — микросервисы лучше чувствуют себя в cloud.
  • 0

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


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

    • 0
      Куски монолита тоже можно «вынести» на отдельные базы.
      некоторые части должны все-таки работать с согласованным хранилищем.
      Зависит от бизнес процессов.
      • 0

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

  • 0
    Единственные преимущество микросервисов — горизонтальное масштабирование. Если оно вообще на вашем проекте нужно, так как дает снижение производительности, если оно не нужно.

    Все остальное прекрасно реализуется на монолите.
  • +1
    Обсуждая микросервисы vs монолиты, нужно договориться, о каком монолите речь.
    Просто у кого-то в голове возникает образ некого скомпилированного исполняемого файла, который при всем желании невозможно масштабировать количеством запущенных копий и балансировщиком перед ними.
    А если представить RAILS-приложение(и подобные), которое вроде как монолит, то там прекрасно всё масштабируется. Тут единственный существенный минус — это выкатка новых версий подсистем монолита.
    • 0
      Масштабируется, но не прекрасно. Один только роутинг может занимать заметное время, если у вас тысячи роутов на регулярках. Да и сами обработчики займут место в памяти, даже если не вызываются. Прогретые кэши для всех них и т. п. А по факту реально используются юзерами с десяток, а все остальное раз в году для отчёта дергается или нового суперадмина назначить.
      • 0
        Согласен, но быстродействие и потребление ресурсов (а я не думаю, что уж так много лишний «груз» кушает, конкретно в рельсах) это лишь пара критериев. Да, оба показатели будут хуже заточенных решений, вопрос насколько.
        Зато, например, какая хорошая утилизация железа. Есть 10 серверов, раскатываем монолит на все сервера и гоним через балансировщик запросы. А в случае с микросервисами придется решать задачку — какой сервис на какую/какие машины раскинуть. В итоге часть железа простаивает, ибо заложили под пики нагрузки. Это можно победить, но ценою усложнения системы.
        • +1
          Утилизация как раз обычно с микросервисами лучше. Например, редко используемая функция (ежедневный отчёт какой-нибудь) требует несколько гигабайт оперативки и грузит процессор длительное время на 100%, а остальные вполне работают на сотне мегабайт и в основном ждут ответа от СУБД. Выносим её в микросервис и нам нужна только одна машина с гигабайтами, остальные по сотне мегабайт.
          • 0

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

            • 0
              Студент?
            • 0
              Реплика тут не причём, говорим о формировании самого отчёта средствами приложения, а не СУБД. Из СУБД данные пришли (из реплики или нет — приложению не важно), а мы на их основе формируем представление для пользователя.
              • 0

                Так формирование отчёта по уже выбранным данным не требует гигабайтов оперативки, если это не отчёт на несколько тысяч листов. SQL для того и существует, чтобы из БД только нужные для отчёта цифры достать. Или Вы имеете в виду, что можно косячно формировать отчёт, но вынести это в микросервис и уже будет не так заметно, что отчёт формируется чёрти как?

                • 0
                  Как вариант, да, не будет заметно. А вообще отчёты бывают разные, бывают и на тысячи листов для гос органов, например.
          • +1

            Забыли про ещё один момент: цена добавления и последующего удаления временной функциональности из монолита.
            Когда есть монолит и есть запрос «доделать существующее, но хитро» то есть большой соблазн это сделать именно в рамках монолита, хотя и известно, что это нужно временно (спустя год эта функциональность уже будет не нужна). Что же, добавляем функциональность, дорабатываем её, развиваем, а через некоторое время её нужно будет удалять и «выкорчевать» вросший в монолит код уже будет непросто. А если не выкорчёвывать, то будет мёртвый код, который будет постоянно мешать обновлять фреймворки и языки программирования и т.д. и т.п.


            А если сделать под этот запрос отдельное приложение, то удалить его будет очень просто :-)

            • 0
              И это хорошо если заранее известно, что фича временная.
            • 0
              Позвольте с вами не согласиться. Вам в любом случае нужно временную функциональность:
              1. Вызывать;
              2. Обрабатывать;
              3. Сохранять результат.
              Это означает, что в любом случае эта функциональность, что в монолите, что в микросервисах будет:
              1. Вызываться;
              2. Обрабатываться;
              3. Сохраняться.
              Это означает, что в любом случае вам нужно добавить, а потом и удалить код для:
              1. Вызова;
              2. Обработки;
              3. Сохранения.
              И, если вы не глупый человек, то все файлы, реализующие эту фичу вы поместите в отдельный каталог, а в каждом месте использования вне этого каталога добавите себе комментарий BEGIN_TEMPORARY_FEATURE_NO <...> END_TEMPORARY_FEATURE_NO, по которому использование этой фичи можно будет найти (и удалить). То же самое для всех таблиц и прочего. В любом случае, что в микросервисах, что в монолите. А если пропустить часть кода, то приложение в любом случае либо не соберётся, либо будет нестабильным, что в случае монолита, что в случае микросервисов.

              Если вы считаете, что я в чём-то ошибаюсь — скажите, в чём?
              • –1
                1. Вызывать можно банальным редиректом или отдельным upstream'ом в Nginx.
                2. Обрабатываться оно будет в отдельном приложении-микросервисе
                3. Сохраняться будет в отдельную БД.

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


                Да, в монолите это всё тоже можно делать, но сложность монолита начинает расти, и разбираться в его коде тоже становится сложнее.

                • +1
                  1) Его всё ещё нужно делать. Без разницы, как именно происходит вызов, данные для вызова должны быть подготовлены и упакованы. То есть код вызова в любом случае будет внедрён во все связанные модули. И должен будет удаляться оттуда. И если вы наивно полагаете, что код микросервисов не будет становиться сложнее, чем код монолита, (как минимум, столь же сложнее, как и) от того, что 20 микросервисов теперь будут дёргать нового временного друга, вы не очень умны.
                  2) Обработка не в смысле выполнение временной функциональности, а в смысле реакции остальной системы на возможные сценарии работы временной функциональности. Она в любом случае должна будет покрывать все стандартные ситуации работы Это я не про вылеты-перезапуски, а про вполне буднечные запросы-оповещения «я покушал» и «я покакал».
                  3) Данные подготавливаются не для повышения энтропии, а для вполне себе утилитарных нужд. Это значит, что они либо будут переводить систему в другое состояние (например, эмуляция оборудования), либо отображаться пользователю этой самой фичи (нужно будет создать запросы и, возможно, UIшки для отображения данных). То есть потребители данных должны получить унифицированный интерфейс, который возникнет не из воздуха, а будет внедрён в существующие модули соответствующей функциональности. А потом — удалён. И если вы думаете, что в микросервисах проще создавать эти самые связи внутри модулей, чем у монолита, опять же, вы либо не особо понимаете разницу, либо программировали монолиты в те времена, когда были говнокодером.

                  Иными словами, мантра «отдельное приложение» лично мне ничего не говорит. Да, есть лёгкость горизонтального масштабирования, а унифицированный API с удобным встраиванием есть? А отладка как, не хромает? Удобно ради какой-нибудь банальной мелочи целый микросервис городить и гонять тонны данных вместо внедрения пусть и неуместного в каком-нибудь контексте кода?

                  Да, сложность монолита растёт, но она растёт не быстрее, чем сложность взаимосвязей микросервисов.
                  • –1

                    У вас какой-то переусложнённый пример в голове, как мне кажется.


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


                    Дано: веб-сайт с функциональностью создания опросов для пользователей (не основная функциональность, но есть).
                    Задача: сделать более хитрые опросы да ещё в разрезе подчинённых организаций (что-то типа, устроило ли вас обслуживание). Аутентификация-авторизация не нужна, UI отдельный, нужна выгрузка результатов в Excel. Взаимосвязи с остальным сайтом 0 (ноль).
                    Как сделали: добавили новые типы опросов (куча условной логики везде), новые шаблоны, справочник долбаных организаций в админке и ещё одна библиотека для работы с Excel (чем не устроила предыдущая, история не сохранила). А потом ещё некоторые из организаций начали активно себе накручивать голоса (вот тут приехала нагрузка, часть из которой была вызвана логикой отложенной обработки голосов, не нужной именно этой функциональности).
                    Как надо было сделать: скопировать всю базовую функциональность в отдельное приложение с отдельной базой, доработать её там, навернуть любых библиотек и наворотов по желанию, развернуть на отдельном домене и сервере и после того, как оно поработало и заказчик получил свои результаты — удалить нафиг сразу вместе с той виртуалкой, на которой оно было развёрнуто.

                    • +1
                      Сферический в вакууме.

                      А приведённая вами в пример задача в её текущей формулировке звучит скорее «нам дали протухшую задачу, мы наспех дерьмово спроектировали модули и не сделали бекапов, поэтому не проехали на Оке и пришлось вызывать говномесные тачки». Ваше решение «сделать всё то же самое, но на бекапе». Иными словами, у вас в любом случае были бы и новые шаблоны, и справочник долбаных организаций в админке, и ещё одна библиотека для работы с Excel, и куча условной логики везде. Ничего бы не изменилось. Ваша основная проблема в том, что никто не подумал изначально сделать опросы максимально изолированным модулем, чтобы его изменение не требовало такой боли. Проблема не в том, что opinion_poll.php был куском Monolith, а в том, что он не был ограничен opinion_poll.php и opinion_poll.html
      • 0

        Кстати, роуты в Rails проверяются по порядку, так что если у Вас реально проблема с тысячами неиспользуемых роутов, то вынесите десяток реально используемых на самый верх routes.rb и остальные роуты будут отнимать ресурсы на проверку раз в году, или когда там до них дело дойдёт )

        • 0
          В память всё равно загрузятся сразу :) И речь не конкретно о Rails, а подобных фреймворках в целом, в которых могут проверяться все роуты, а выбираться наиболее точно совпадающий. Например, если для роута get_user с путем /user не указан метод, а для post_user с тем же путем указан метод POST, то роутинг должен выбрать второй, если запрос на этот путь отправлен методом POST, независимо от того какой указан раньше.
          • 0

            Естественно сопоставление роутов идёт с учётом метода. Это не значит, что из-за этого проверять придётся все. Но в память загрузятся все — это да… несколько десятков килобайт займут )))

            • 0
              Я про то, что есть роуты без указания метода, а есть такой же но с методом. Запрос с этим методом должен отработать по этому роутеру, а со всеми остальными по первому, независимо от ого какой выше, какой ниже. Тут только всё проверять в общем случае без оптимизаций типа дерева роутов и т. п.
              • 0

                А я понял, Вы про роуты, которые для всех методов подходят. В таком случае в Rails будут просто игнориться все последующие дубликаты этого роута с указанием конкретного HTTP-метода. Хотя допускаю, что где-то роутинг может искать best match до победного конца, но имхо это странный вариант… first match будет всегда работать быстрее.

                • 0
                  Ничего странного, очень удобно.
  • +1

    Пример: небольшая компания делает внутренний проект, пользователей несколько десятков по стране. Делает один человек. Естественно получается монолит в каком-то смысле. Потом добавляется второй проект, как-то связанный с первым — второй монолит. Потом ещё несколько. Все они взаимодействуют. Потом оказывается, что внутри первого есть малосвязанные компоненты, как-то друг с другом общающиеся все по разному — кто через базу, кто через CGI скрипт со странными форматами передачи данных, кто-то поставляет на соседний сервер обновления через rsync — зоопарк. Так как проект растянулся на десятилетия, есть архаичные версии систем, языков, технологий и библиотек. Проект работает сам собой годами, без серьёзного вмешательства. И тут надо что-то поменять. Небольшое. Например добавить 1000 пользователей. И оказывается что поменяв в одном месте — поменяется и в другом, а даже наличие описания не помогает потому что архитектура требует одного сервера в узком месте. Перенести на новую ОС не удаётся — там давно не поддерживаются старые библиотеки. Базы данных, которые обслуживают части монолита, не поддерживаются уже 10 лет но там где запущены — работают как часы и все забыли что они есть. Вот реальная проблема реальных систем не топовых компаний. На этапе разработки термина "микросервисы" не было. Теперь понятно, что надо было стандартизировать общение между компонентами и разделять на куски в расчёте на поддержку некоторых кусков 20 лет без изменений, а других править каждый день.


    Сейчас огромный плюс разделения на микросервисы — возможность разделения задачи на разные языки и технологии и поддержка маленьких компонентов случайными людьми — по мере необходимости нанимаем специалиста по эрлангу или перлу или яве на текущую задачу на пару месяцев и всё хорошо. Сервис маленький, описание простое, протестировать можно. 20 лет назад были модны программисты-универсалы, сейчас больше одного-двух языков/технологий знают единицы. А выбор языка диктуется самыми разными причинами — например описание API на swagger довольно жёстко задаёт выбор одной из 20-ти технологий из которых половина Java.


    А облака… это всё хорошо, но как-то облачно. Масса организаций в облако не отдаст ничего.


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

    • 0
      Все правильно, но сама задача «Разбить проект на слабосвязанные компоненты с жесткими контрактами на взаимодействие между ним» очень непростая, особенно если надо заглянуть в будущее. И по идее уже не так важно, внутри монолита дробить или между сервисами.
      Мне кажется оптимальным начать с монолита, а походу смотреть и находить линии «разреза». Так не только я считаю, и другие видят в этом нормальную стратегию.
      • 0

        Реальная стратегия для нового проекта — "как получится" :)

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

      Микросервис вовсе не значит что он будет микро в плане количества стрчоек кода. Он микро в плане количества решаемых задач. Микросервис делает всего одну вещь, но делает её хорошо, быстро и надежно. Unix-way короче

  • +1
    А БД, вебсервер (mysql, redis, nginx...) относятся к микросервису? Отдельный процесс с коммуникацией «по сети», вроде подходит. Если да, то получается все изначально используют микросервисы.
    • 0

      не совсем)) эти вещи не решают бизнес-задач. Они решают технические вопросы хранения данных, общения с клиентом, еще чтото, но не решают бизнес-задач. Это инфраструктура для микросервиса)

      • +1
        бизнес-задач
        Это очень расплывчатое понятие, а модуль авторизации, модуль суммирования массива или другая арифметика, модуль поиска числа в массиве — бизнес задачи или нет? А если сервис (node.js) просто пересылает данные из nginx в mysql и обратно — бизнес логика/микросервис?

        Я считаю проще, если я делаю какой-то (сетевой) вызов в другой самостоятельный процесс, то этот процесс — (микро)-сервис. Просто mysql/redis — это уже обыденность и не хочется признавать это микросервисами, т.к. микросервисы — это вроде как повышенная сложность. К тому же некоторые хранят часть логики в самой БД.
        • 0

          Бизнес задачи это вполне конкретные понятия. Вы зачем собственно программу пишете? Вот сервис авторизации/аутентификации вполне решает бизнес-задачу по ограничению доступа к системе. Если бы он не решал, то его небыло бы в вашей системе, разве не так?

          • +1
            Не так все просто, как сказали выше, «очень расплывчатое понятие»
            Бизнес делает «бабки», на прямую этот сервис авторизации «бабки не делает», тоесть с точки зрения бизнеса это техническая поддержка/обслуга необходимая для выполнения бизнес процесса(ключевое — приносящий бабки), если только бизнес не продает услугу «авторизации/аутентификации», и вообще сейчас мода, что в бизнесе остаются только бизнес задачи, все остальное на «аутосорс», тоесть «авторизации/аутентификации» организовать через какой-нибудь «Центр авторизации TM ID» или Google или vk, выбрать из них лучшей по качеству услуги, тоже самое, как не держать уборщицу в штате, а вывести ее на «аутосорс», аналогично все то, что не требует менее «1 целой штатной единицы» по мнению менеджера.
            Вот отсюда, и дует ветер всех этих «микро сервисов», чтобы в IT организовать тотже «ауторос», тоесть нужен для выполнения бизнес задачи (условно — продача чайников) — поиск, выбираем из поставщиков google/bing/yandex и.т.д., большие «дяди» вложились в cloud, теперь услуги продавать, окупать инвестиции.

            Писал уже выше пример — кейс, для вашего бизнес процесса, нужны допустим какие-то вычисления, вот их то вы и заказываете (а docker просто обвязка, которая теоретически позволяет экономить бабло обеим сторонам, по идеи выгоднее виртуалок), и заказать эти вычисления вы, как у amazon, так и у google, и выбрать наиболее подходящий для себя вариант ---> по факту это загон в cloud, всем известно, как легко перевести часть процессов в cloud, и как сложно их оттуда порой выцара́пывать.
            Прогноз: Как только «корпораты», переведут все часть процессов в cloud, так ловушка и захлопнется, и пойдет увеличение тарифов, ничего нового в общем. Но конкуренция среди cloud сервисов будет возрастать и это хорошо.
            Вот по этому, ваши сервисы и назвали «микро», ибо они действуют в рамках большого сервиса, который предоставляет cloud провайдер.
            • 0

              Не совсем в тему микросервисов, но хочу заметить, что слово "бизнес" применительно к архитектуре приложения не имеет (в общем случае) отношения к коммерции, а обозначает ту "пользу", которую приносит конкретное приложение.


              Поэтому сервис авторизации для конкретного приложения — это бизнес-функциональность, но в то же время используемая библиотека для OAuth2 — это уже не бизнес-часть, т.к. она универсальна и не привязана к предметной области.


              Поэтому суммирование массива — не бизнес-функциональность, если у нас, конечно, не приложение по суммированию массивов (Excel).

    • 0
      Все (почти) используют, но не все пишут :)
      • 0
        Микро-сервис написанный не вами не перестает быть микро-сервисом.
        • 0
          Команда пишет приложение, реализующие какие-то функции. От того, что это приложение используется сторонними приложениями как сервис или даже микросервис, от того, что это приложение использует сторонние приложения как сервисы или микросервис, никак не зависит является ли архитектура самого приложения монолитной или сервисно-ориентированной.
  • 0
    -del-
  • +1
    Итак, отчего мы отказываемся в случае перехода на микросервисы
    1) От транзакций. Главный минус
    2) Получаем проблемы с версионной совместимостью этих микросервисов между собой
    3) Вместо работы внутри процессора и системной шины мы гоняем данные по медленной сети и всему сетевому стеку. Сильное замедление работы. Получаем сильную зависимость от качества сети
    4) Повышение надежности — миф. Приложение не может работать без какого-то компонента. Это будет некорректная работа.
    5) Все эти микросервисы в сумме потребляют больше памяти и ресурсов, чем монолит
    6) Вынужденное дублирование кода. Либо приходится делать какие-то отдельные проекты с общим кодом
    7) Невозможность рефакторинга. Мы получаем кучу внешних интерфейсов, которые нельзя трогать. Либо придется править одновременно все микросервисы
    8) Сложность при обновлении, если изменился внешний интерфес. Приходится обновлять одновременно несколько микросервисов. Если будет рассинхронизация — клиенты получат ошибки.
    9) Сложность правки базы. Сложно понять, использует ли эту таблицу какой-то другой микросервис. Приходится пересматривать код всех микросервисов. И опять возникает проблема одновременного обновления.

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

    • 0

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

      • 0
        >У каждого микросервиса должна быть своя база
        т.е. отказываемся от форенкеев и дублируем данные?
        • 0

          Если данные надо дублировать — значит, граница ответственности микросервиса обозначена неправильно.

          • 0
            Нормально она может быть обозначена, например, когда одна «физическая» сущность в одном контексте является полноценной доменной сущностью, а в другом лишь значением атрибута. Например, частый случай — физическое лицо. В разных бизнес-процессах требуются разные данные о нём, в одних может быть нужна самая актуальная информация о нём, в других — информация на момент совершения информации. И идея сделать единый микросервис, отвечающие за все данные физлиц не самая лучшая, даже если пренебрегать лишними сетевыми вызовами и т. п., просто с точки зрения сложности самой сущности.
      • 0
        кстати, что насчет ресурсов на работу кучи баз. Один только оракл кушает минимум 2 гига оперативной памяти
        • 0

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

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

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

    • +1
      1. От каких транзакций вы отказываетесь?
      2. Никаких проблем нет. Вас никто не заставляет ломать обратную совместимость в минорных патчах. При необходимости таких изменений используется стандартное решение через /api/v1/… /api/v2/… при том вас никто не заставляет поддерживать 100500 версий. Пользователи этих апи — это все тоже ваше приложение и ваши коллеги, которых их саппортят. Приняли решение ломать совместимость, опубликовали соответсвующий раздел в доках, оповестили все команды и поставили дедлайн до которого они должны апнуться.
      3. Да, безусловно так, но никто не заставляет вас гонять данные через весь земной шар. Здажержки в локальной сети не такие уж и большие, особенно по сравнению с сетевыми задержками между вашим приложением и конечным пользователем. К томуже, шлюз, с которым общается конечный пользователь вполне может работать с остальными микросервисами асинхронно, что сведет сетевые задержки на общение микросервисов практически к константе, не зависящей от количества этих самых микросервисов.
      4. Не поверите, но может. Не случиться ничего страшного, если по какойто причине упадет рассылка писем. Да пользователи не получат писем некоторое время, но как только рассылка поднимется все задачи с очереди будут выполнены. Останется досутпной публичная часть системы, если вдруг упадет авторизация. Более того, залогиненые юзеры смогут продолжать работу. Да, когда падает критически важный микросервис, то работа встанет. Но даже в таком случае. На прошлой рабте у нас был здоровенный монолит, деплой которого на прод сервера в двух датацентрах занимал около 3 часов времени. Фикс в 5 минут времени деплоится 3 часа. Микросервисы меньше, проще, легче разворачиваются.
      5. Наоборот, микросервисы лучше утилизируют ресурсы. Их можно разворачивать на машинах оптимизированых на ту или иную нагрузку. Файлохранилищам нужны быстрые и надежные диски. кеши требовательны к объему озу и так дальше. Если ваш логин сервис не справляется с количеством жалеющих залогинится, то вам нужен просто еще один логин сервис, а не все огромное приложение.
      6. Отдельные проекты с общим кодом — плохой вариант. Да, нужно дублирование кода. Но это не так страшно. DDD отличо ложиться на идею микросервисов. Сервис владелец имеет код позволяющий создавать/менять/удалять некие сущности. Сервисы которым нужны эти сущности получают упрощенный код, рид-онли модели, на которые мапятся ответы апи сервиса-владельца. Да, лишний код, но он пишется один раз, да и пишется громко сказано. ИДЕ спокойно нагенерит класс с конструктором и пачкой геттеров.
      7. Это тоже что версионирование. Помогает с этим бороться во первых слоеная архитектура. Вы можете как угодно менять бизнес логику приложения, оставляя неизменный внешний интерфейс пока это возможно. Как только это становится невозможно, смотрите пункт 2. В монолите при таких изменениях вам точно также придется править все места, где модуль используется.
      8. Вы уже третий раз говорите одно и тоже. И я третий раз вам скажу, что эта проблема хоть и существует, но не такая страшная как вы её описываете.
      9. Вообще не проблема, ибо у каждого микросервиса есть своя бд для своих нужд и апи других сервисов для данных, которыми сервис не владеет.

      Ну и как итог. Микросервисы далеко не серебрянная пуля. Более того, для большинства приложений они не нужны. Любой нормальный монолит вцелом пишеться как набор независимых модулей (читай микросервисов), работающих в пределах единого приложения. Сразу начинать писать приложение как микросервис — это глупая затея. На начальном этапе вы не установите границе микросервисов достаточно точно и как результат получите плохую масштабируемость и сильную связанность. Микросервисы — это следующий этап развития. Когда монолит становится слишком большим. Становится слишком большой команда, которая его поддерживает. Когда в монолите явно выделились группы независимых модулей которые решают бщую проблему и становится ясно, что их можно вынести в отдельное приложение. Когда видно какие компоненты зависят от каких данных и так дальше. Вот тогда приходят микросервисы.

      • 0
        как делать одну транзакцию поверх нескольких микросервисов?
        Например модуль складского учета и финансовый модуль. Произошла ошибка в финансовом модуле. Как откатить транзацию в модуле складского учета?
        • 0

          Не надо откатывать. Надо повторять попытки достучаться до финансового модуля в фоне. Это и есть та самая устойчивость к отказам — складскому учету не нужен постоянно работающий финансовый модуль.

        • 0

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

          • –1
            итого какие-то костыли и велосипеды вместо стандартных транзакций. Про это я и говорил в самом начале
            • 0

              У вас ошибка в комментарии:


              вместо медленных транзакций
              • 0
                Итого мы отказываемся от медленных транзакций чтобы использовать свои велосипеды. Верно?
                • 0

                  Почему вы стандартные решения называете велосипедами?

                  • 0
                    Как вариант можно сущностям добавить статус. И пока статус не станет подтвержденным их видно, но ими нельзя воспользоваться. Соотвественно можно мониторить зависшие в невесомости вещи и принимать какието решения/меры по их исправлению.

                    это явно не стандартное решение.
                    Ендпоинты — тоже довольно редко применяются и поддерживаются далеко не везде
                    • –1

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

                      • 0
                        Это наглядный пример, как (микро-)сервисы делают код проще.
        • 0
          Произошла ошибка в финансовом модуле. Как откатить транзацию в модуле складского учета?
          Вообще эти 2 могут быть в одном микросервисе, в разных «черных ящиках» (модулях). Но если все же они отдельно, вызов финансового модуля должен быть быстрый (0,1-1 сек), в итоге если фин. модуль возвращает ошибку, то откатываете незакрытую транзакцию в складском.

          Если фин. модуль выполняет метод долго (1-10 мин), то у вас проблемы другого плана, т.к. такие долгие транзакции очень не желательны (особенно которые блокируют «пол базы»). И если нет возможности ускорить, например это внешний платежный сервис, который ждет когда пользователь кликнет кнопку, то вам нужно использовать 2-х фазный комит. И микросервисы в этом случае не осложняют ситуацию.

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

          PS: Я за «монолит на старте»
          • 0
            Вообще эти 2 могут быть в одном микросервисе, в разных «черных ящиках» (модулях).

            Не могут. Это будет уже не микросервис.


            PS Я за макросервисы и монолит на старте.

        • 0
          как делать одну транзакцию поверх нескольких микросервисов?

          Вариантов куча, от самых простых типа залогировали ошибку, саппорт пускай разбирается, до промышленных координаторов транзакций от ведущих брендов типа МС и Оракла. Тем более на практике всегда есть транзакции, которые вроде бы одно целое, типа получил деньги и отдал товар, но в особых случаях откатить не получится, если что-то пошло не так, например, деньги взяли в кассу, провели и свет отрубился, ни деньги не вернуть, ни товар не отгрузить.
          • 0

            Ну или самый простой вариант — это не разносить транзакционные сервисы по разным микросервисам.

            • 0
              Этот вариант имеет свои ограничения.
        • 0
          Погуглить
          — 2 phase commit
          — eventual consistency

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

    • 0

      Такое впечатление, что микросервисы, по-вашему, — это как dll, только доступные по сети.

  • 0
    Самое большое преимущество микросервисов я вижу в их взаимозаменяемости. Если есть хороший стандартный интерфейс, можно легко поменять одну имплементацию/версию на другую (в т.ч. реализованную на другом ЯП/платформе), не трогая всю остальную систему. Жертвовать же производительностью (общение сервисов через сеть) за счёт небольшой экономии ОЗУ (создание новых экземпляров только нескольких сервисов на другом сервере вместо нового экземпляра целого монолита) не вижу никакого смысла.
    • 0
      ну да, какой-то универсальный сервис. Например сервис адресов, которому не нужны ни транзакции, ни согласованность данных.
      Но пытаться делить неразделимые вещи не стоит
  • 0
    Допустим у нас есть приложение в котором пользователи могут регистрироваться, авторизоваться и что-то публиковать. Пользователи могут дружить. И каждый пользователь может видеть только публикации друзей.
    А также пользователь может заблокировать любого другого пользователя, даже друга, и тогда заблокированный пользователь не сможет увидеть публикации.
    Как в микросервисах хранить заблокированных пользователей? Ведь они нужны в 2 микросервисах: публикации и друзья.
    • 0

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

      • –1
        Есть микросервис авторизации, и есть микросервис правки данных. При правке нужно сохранять id пользователя, совершившего эту правку.
        Как это сделать, если базы разные?
        • 0

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

          • 0
            т.е. отказываемся от форенкеев (целостности базы)
            • +2

              База самого микросервиса вполне целостная. Целосность расшаренных данных зависит от от логики приложения. Только и всего. Допустим ваш сервис постинга может удалять/помечать удаленными записи автора, по которому приходит 404 с сервиса пользователей.
              Почему вас не возмущает, что если я зареган через соц сети, а потом взял и удалился из соцсети, то на вашем сайте я по прежнему есть? Смотрите на микросервисы как на независимые приложения. У приложения есть "свои данные", целостность которых контролируется базой этого приложения. Есть внешние, которые от этого приложения не зависят (Юзер удалился). Максимум что, сервис юзеров может бросить ивент об удалении юзера, а сервис постов подписатсья на него и както прорегаировать. Или не реагировать вовсе. Все зависит от бизнес-логика приложения.


              ЗЫ. существуют монолиты исползьющие несколько хранилищ одновременно. При этом это не всегда даже РСУБД. Это может быть документоориентированная бд, может быть кей-велью хранилище, графовая бд, даже банальные файлы или удаленные сервисы всяких амазонов и иже с ними. Как же монолит поможет обеспечить целосность данных в этом случае? О каких венешних ключах может идти речь?

              • 0
                База самого микросервиса вполне целостная.

                только в пределах одного микросервиса.
                Что делать, если id пользователей рассинхронизируются между базами?
                • 0

                  Каким образом? Всегда есть сервис владелец, который контролирует создание. И сервисы клиенты которые оперируют рид-онли данными полученными от сервиса-владельца. Рассинхрон может быть, если сервис-клиент напрямую удалит или изменит данные в чужой базе, но это противоречит всей идеологии микросервисной архитектуры

                  • 0
                    Ну зачем-то же придумали форенкеи как метод обеспечения целостности
                    • +2

                      каждому инструменту свое применение. Внешние ключи отнюдь не панацея, к тому же довольно тяжелая штука при вставке/изменении/удалении записей.

                    • 0

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


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

                      • 0
                        Как это ушел, он вам об этом сказал? Если нет то откуда вы знаете что он ушел, может он после 5, 10 лет вернется.
              • 0
                Любые распределённые данные без единого транзакционного центра всегда вероятностны. Всегда есть вероятность, что данные на одном сервере уже изменились с того момента, как мы получили последний ответ. И, что самое ужасное, у нас нет способа сказать «Всем ЦЫЦ! Батька думает.»

                З.Ы. Монопольное владение.
            • 0
              т.е. отказываемся от форенкеев (целостности базы)

              Не драматизируйте. Всего лишь отказываемся от обеспечения целости данных в рамках всего приложения средствами СУБД. В рамках микросервисов целостность обеспечивается средствами СУБД, а целостность между ними обеспечивается другими средствами, если она вообще нужна.
          • 0
            Ещё пример. И в финансовом, и в складском модуле нужно ФИО клиента при выводе списка.
            Что вы предлагаете делать: дублировать их в разных базах или дергать отдельный запрос на каждую запись в списке?
            • 0

              Дублировать.


              Не смысла бороться за размер хранимых данных кроме как в самой большой таблице. В складском модуле самой большой таблицей будет журнал операций. Каждый клиент будет связан как минимум с двумя записями журнала, а скорее всего их будет еще больше.

              • 0
                а что делать, если эти ФИО поменяются? Как их синхронизировать?
                • 0

                  Тут три варианта.


                  1. Никак! ФИО в журнале операций должно быть таким же, что и документах (например, в накладной). А там данные измениться не могут.


                  2. При получении свежего токена от пользователя данные о нем в базе обновляются. Таким образом, ФИО в журнале будет старым пока пользователь не обратится (прямо либо опосредовано) к сервису.


                  3. Изменения данных пользователей публикуются другим сервисом, а складской модуль на них подписан.
                  • –1
                    итого стандартную целостность нужно обеспечивать руками и велосипедами
                    • +1

                      Обеспечьте целостность когда документы (накладные, квитанции и прочее) хранятся в документов монге, а юеры в mysql

                      • –1
                        Вы ходите по кругу, mongo и mysql — уже отдельные (не микро) сервисы. Логично, что между ними уже нет взаимодействия, и любые попытки синхронизации ради обеспечения целостности — велосипеды.
                        Потому любые ваши наезды «обеспечьте», вообще-то не по адресу, так как речь идёт именно о том, что (микро-)сервисная архитектура этого сделать не может, на это способен только монолит. То есть распределённая база не может давать гарантии, в ней всё всегда вероятностное. В рамках одного единственного mysql же (или postgresql, который давно уже чавкает жсонами) такую целостность обеспечить очень просто и достаточно дёшево.

                        Ясное дело, что люди переходят на связки манги и мускула не от хорошей жизни, но не нужно, как веганы, верещать во все стороны «Я давлюсь этим сельдереем уже два месяца и отлично себя чувствую, а вы такие злые из-за мяса.» Вы НЕ можете обеспечить 100% целостности и синхронности в микросервисах, и никогда не сможете. Факт. Но вы можете повысить производительность и понизить вероятность ошибок так, что погрешности с лихвой покроются прибылью. Тоже факт. И не нужно городить что-то ещё.
                        • 0
                          Вы НЕ можете обеспечить 100% целостности и синхронности в микросервисах, и никогда не сможете.

                          Вы отрицаете, что не только CA системы, но и просто C (в терминах CAP) существуют и эксплуатируются?
                          • 0
                            Нет, я её цитирую. Любая БД не может быть одновременно согласованной, доступной и распределённой на несколько транзакционых центров. Микросервисы — это именно выделение нескольких транзакционных центров. Значит, у вас не будет либо гарантии согласованности данных, либо гарантии доступности сервиса, и любая операция в такой системе будет вероятностная.

                            Вы сами написали, что вне единого транзакционного центра нужно рвать жопу сложными логами и прочими приблудами. Вы сами написали, что вне единого транзакционного центра мы можем гарантировать согласованность лишь атомарной операции. А теперь вы спрашиваете такие, простите за выражение, тупые вопросы? Повторюсь, я их не отрицаю. Я констатирую, что CA и C системы не могут быть распределёнными по определению.
                            • 0
                              Не могут быть распределенными (но не по определению, а по гипотезе, подтвержденной наблюдениями, но не доказанной теоретически) CAP системы, либо CA, либо CP, либо AP. И это относится в том числе к клиент-серверным и трехзвенным архитектурам — они тоже распределенные.
                              • 0
                                Подловил, по гипотезе.
                                Остальное верно, Они тоже вероятностные. Отсечение вероятностей возможно только монопольным владением, о чём монолиты и есть. Ибо если приложение монолит, оно точно знает, что кроме него самого никто не мог внести изменения в его хранилище, и что транзакции никто, кроме него вносить не может. А микросервисы? А что микросервисы? Сегодня он есть, а завтра их десять. Какие гарантии?
                                • 0
                                  Микросервисы предоставляют на выбор либо CA, либо CP, либо AP (можно, конечно и меньше). Нужна согласованность обязательно — можно пожертвовать доступностью или устойчивостью. Причём это применяется и без микросервисов в обычном понимании. Есть транзакционный центр типа постгреса, для него пару синхронных реплик на случай отказа мастера. Пока обе реплики не подтвердят, что приняли изменения, мастер клиенту не сообщит о завершении транзакции.
                                  • 0
                                    Всё верно. Вот только это не противоречит тому, что я написал. А написал я, что с разбиением на микросервисы и, соответственно, на множество транзакционных центров мы теряем гарантии, как минимум доступности сервиса целиком, а то и целостности данных (монопольное владение данными в микросервисах, в общем, не поощряется, дублирование записей между репликами микросервиса, в общем, не работает, все системы разбиения на кластеры нужно прикручивать извне). Мы и так её не имели учитывая жестокий реальный мир, а теперь она дополнительно снижается, и весьма серьёзно. Написал я, что попытки дать гарантии повышает сложность взаимодействия систем (даже внутри постгреса разворачивать реплики не очень просто и дёшево, а скрестить манго и мускул — тот ещё фрукт получится), и большую часть кода придётся написать самому. Так в чём я был не прав?
                                    • 0
                                      В реальном жестоком мире гарантий соблюдения CAP не даёт никто. Более того, для повышения доступности вводят в монолитные системы распределенность в виде репликаций и прочих HA-штук. Это если не учитывать, что даже тот же Postgres по сути своей не является монолитом, а лишь условно монолитным ядром, взаимодействующим с, как минимум, ОС, которая взаимодействует с, как минимум, железом. И на уровне Postgres-ОС, и на уровне ОС-железо, тратится множество усилий для увеличения хотя бы целостности данных, чтобы клиент, получивший от Postgres подтверждение, что транзакция выполнена был уверен, что в сложной распределенной (с точки зрения процессов) системе его данные потеряются с минимальной вероятностью. Но это не гарантии, это лишь обещание «мы сделали всё, что смогли, но мы не боги».

                                      На самом деле микросервисы мы используем очень давно, просто теперь есть тренд не только использовать, написанные (а то и воплощенные в железе) кем-то, но и писать их самим. Да, сложность разработки (в плане увеличения количества контролируемых разработчиком процессов и связей между ними) увеличивается, но это плата за другие преимущества, прежде всего за возможность дешевого горизонтального масштабирования в целях, прежде всего, увеличения доступности архитектурными средствами самого приложения, а не внешними «микросервисами» типа СУБД.
                                      • 0
                                        И где мой комментарий противоречит этому? Нигде. О чём спорим? О любви к спорам? Не имеет смысла, срач — это наше всё, и нет никого, кто любил бы нас сильнее, чем святой вентилятор и присвятая понажористая жижица.
                                        • 0
                                          Вы используете слишком категоричные утверждения, заявляя, что, с одной стороны, монолит дает гарантии CAP, а с другой, что микросервисная архитектура не может гарантировать даже C.

                                          А на самом деле, классическая клиент-серверная или трехзвенная архитектура с РСУБД не может обеспечить CAP (даже сама СУБД не может, поскольку распределяет функции между своим ядром и ОС, имея вероятность как отрапортовать о законченной транзакции, которую по независящим от СУБД причинам клиент не увидит, так и закончить транзакцию, не уведомив об этом клиента), а микросервисная может обеспечить CA, CP или AP на выбор, так же как классика. Ничем они принципиально не отличаются, кроме того, что в случае микросервисной архитектуры на разработчика возлагается бОльшая ответственность за балансирование между метриками CAP, все из которых не могут достигать 100% ни в одной практически возможной архитектуре, только лишь вероятностные, пускай и с кучей девяток, даже в самых дорогих проектах типа космических, где применяется многократное резервирование всего и вся лишь с целью набрать побольше девяток, но стопроцентных гарантий нет, ведь сама аппаратная база носит вероятностный характер, а для защиты от сбоев используются методы теорвера и матстатистики, уменьшающие вероятность незамеченных сбоев и даже где-то исправляющие их, но не сводящие её к 0%. Например, какая-нибудь ECC-память способна исправить один и заметить ошибку в двух неправильных битах в слове, но если ошибка в трёх, то она даже обнаружить это может быть неспособна.

                                          Весь срач из-за нежелания большинства разработчиков так называемых монолитов признать, что они давно используют сервис-ориентированные архитектуры, просто сами разрабатывают только один сервис из множества используемых их приложением, перекладывая ответственность за CAP-метрики всего приложения на плечи разработчиков этих сервисов таких как СУБД, веб-серверы, и ОС.
                                          • 0
                                            Ну да, всё так. С этим никто не спорит, чистых монолитов слишком мало, чтобы о них писать, мы это с вами выше обсудили. Только не об этом срач. Мы же с вами не сошлись на том, что мы зовём микросервисной архитектурой, и в чём её отличие от архитектуры сервисной и от модульной архитектуры. У нас по прежнему нет чёткого понимания терминов, на которых мы говорим.

                                            Мы можем говорить о микросервисной архитектуре, как о продукте из независимых модулей-приложений с отдельными базами данных и взаимодействии только по HTTP. А о монолите, как о приложении, в котором все части написаны на одном языке и реализуются через внутренние вызовы, которое собрано в общий бинарик, но которое, в принципе, может использовать внешние сервисы через публичный API. И то, и то — радикальные формы архитектуры, имеющие в своём радикализме огромные неустранимые в рамках самих себя проблемы. Монолит — в масштабировании, а микросервисы — в накладных расходах и проблемах с синхронизацией.
                                            А истина, как обычно, где-то посередине, там, где валяются DLL-ки, где куча пайпов и потоков, где разделяемая память трясёт мутексами и критическими секциями и где, прежде всего, продуманная архитектура внутреннего взаимодействия с разделением в тех местах, где оно может понадобиться. Короче, там, где нас нет.
                                            • 0
                                              Отличие от сервисной архитектуры только одно по сути — ответственность каждого отдельного сервиса. Грубо, если блоговый сервис отвечает и за собственно блоги (посты с комментариями) и за управление пользователями, то это сервис. Если доверяет управление отдельному сервису, отвечая только за блоги, то это микросервис.

                                              Протокол взаимодействия сервисов между собой к архитектуре особо не относится. Мы вон активно AMQP используем. И даже разделяемая память и прочие мутексы может быть частью протокола, если условный монолит был однопроцессынм и мы решили его масштабировать горизонтально хотя бы в пределах одного процессора по процессу на ядро.
                                              • 0
                                                А вот тут очень зыбкая почва под ногами. Микросервис отвечает за блоги и только за ленту блогов? Отлично. А разделить его на микросервис работы с БД для простоты миграции, микросервис генерации страницы для гибкой настройки генерируемого контента и микросервис взаимодействия с внешним миром — остальными микросервисами — не хотите?

                                                Вы скажете, это излишнее усложнение? А вот это вопрос дискуссионный. Как и предложенное вами разделение. Есть у меня, например, сервер онлайн-игры, и есть сайт. На нём чат, совмещённый с игровым, лента новостей, лента внутриигровых событий. Аутентификация через клиент. И как делить, что тут микросервис, что тут сервис? В драке на ножах, не иначе. Да и сам сервер, с одной стороны, делится на микросервисы, а с другой — не делится. Потому что есть сотни разделений, которые можно провести для правильных абстракций и ещё тысячи — для неправильных, но всё ещё очень симпатичных. И будет ли такое разделение сервисом или микросервисом — это прекрасная тема для дискуссии за пивком под воблу, но совершенно лишняя у клавиатуры с IDE-шкой на мониторе.

                                                И по протоколу, лично вы, конечно, можете использовать любые, но вы, видимо, не читали самой статьи. А в ней красной линией проходит мысль, что вы делаете это внеправильно, а правильно — через веб-сокеты. Это мысль из статьи, и я с ней не согласен, но эта мысль встречается не впервые, её активно проталкивают.
                                                • 0
                                                  Собственно это и имелось в виду. Микросервис блогов отвечает за записи постов и блогов в БД, отдавая их в каком-то слабо адаптированном для конечного пользователя формате типа JSON. А взаимодействие с внешним миром может осуществляться не только через http endpoints по схеме все-со-всеми, но и через, например, звезду, где в центре какая-нибудь очередь сообщений, или через шину. А html рендеринг (если он вообще на серверной стороне осуществляется, а не на клиенте) происходит на отдельном сервисе шаблонизации.

                                                  Да не надо делить сервисы на микро и «макро» у клавиатуры. Когда ответственность сервиса выродится в ответственность только за одну сущность или за один процесс, тогда можно констатировать, что он стал микросервисом. А можно не констатировать, можете продолжать называть его сервисом.

                                                  Это вы, видимо, невнимательно читали статью, в ней фразы типа «например HTTP», «вроде HTTP» — просто HTTP самый популярный способ для создания интерфейсов микросервисов, особенно на первых этапах разбиения монолита на сервисы, в том числе и микро. Он синхронный, он поддерживается из коробки, наверное, всеми мэйнстрим языками, он простой (если использовать его в качестве транспорта, а не пытаться реализовать всю его семантику). И во многих случаях он уже используется в системе для общения с клиентами.
                                                  • –1
                                                    И в чём тогда отличие микросервисов от любой другой модульной архитектуры, прежде всего, трижды упомянутых мной динамических библиотек? Спойлер: они не такие гибкие.
                                                    Зачем такое повальное поклонение «золотому бычку»? Спойлер: раскрутить тему и продать больше своих решений.

                                                    Всё, что написано в статье, всё целиком уже давно известно. А всё что вы написали, ВСЁ ЦЕЛИКОМ сводится к «наймите толкового системного архитектора». Вот только ни в статье, ни у вас не написано, как обеспечить привычные для монолита согласованность данных, да и организовать транзакции вообще. Готовых решений нет, а все варианты сводятся к «нажарь свою СУБД».

                                                    А я буду стоять на своём «нужно думать, что делаешь — и не поддаваться на веяния моды и чьи-то сладкие речи», И ни Аллах, ни шайтан не смогут сдвинуть этого упёртого осла с его места.
                                                    • 0
                                                      Грубо, сервис — модуль, компонент, вынесенный в отдельный исполняемый (а не линкуемый как библиотека) бинарник, который запускается в отдельном процессе ОС (на практике часто на отдельной машине исключительно с сетевым доступом к процессу клиентами). Главное преимущество перед библиотеками — возможность гибкого горизонтального масштабирования: может один процесс сервиса обслуживать тысячи основных процессов, а могут тысячи процессов сервиса обслуживать один основной процесс. С библиотеками невозможно реализовать второй кейс, и, как правило, не реализуют первый, либо статически линкуя библиотеку, либо загружая все динамически линкуемые библиотеки на старте процесса, используя динамическую линковку по сути лишь для уменьшения размера бинарника, а не по требованию, а после использования сразу выгружая.

                                                      Является ли сервис микросервисом определяется не техническими характеристиками, а архитектурными — количеством ответственностей в рамках общей архитектуры системы — у микросервисов оно стремится к одной.

                                                      Согласованность и транзакционность привычно обеспечивается не самим монолитом, а средствами СУБД в рамках трехзвенной архитектуры: клиент-сервер приложения-СУБД, то есть монолитом является сервер приложений с весьма ограниченным собственным состоянием, а целостность и транзакционную изоляцию он доверяет другому серверу/сервису/микросервису — СУБД. При решении архитектора разбить монолит на сервисы/микросервисы есть множество способов обеспечить согласованность и транзакционность между ними, первый из которых убедиться, что она действительно нужна во всех кейсах, а не суется по привычке, потому что разработчикам это практически ничего не стоит. Нужен индекс для поиска по идентификаторам клиента в таблице заказов, есть первичный ключ у таблицы клиентов, почему бы его не сделать внешним ключом к таблице заказов, даже если от аналитиков/заказчиков не было требования обеспечить ссылочную целостность. Вот есть явное требование что поле «идентификатор клиента» должно иметь возможность ссылаться на несуществующую в таблице клиентов запись, тогда не будут делать внешний ключ, а нету — будут. То же и с транзакционностью. Вот сейчас уничтожаю транзакционность в модуле приема платежей от платежной системы. разработчик модуля писал информацию о сообщении платежной системы о платеже в таблицу для этих сообщений, потом собственно в таблицу платежей финансового модуля, транзакционность явно не использовал, но она во фреймворке по умолчанию. В результате при нарушении целостности во второй таблице мы теряем запись о платеже вообще. Не, ошибка в логи пишется, но читать их начинают только когда клиент приходит жаловаться с чеком платежки на руках.
                                                      • –1
                                                        И что не позволяет библиотеку реализовать и как приложение-(микро-)сервис, и как подключаемый модуль? rundll32.exe не в десятке выпустили, так-то.

                                                        Это число всегда зависит от нашей точки зрения. Для одних чат для работы с клиентами будет микросервисом, а для других он будет сложным продуктом из скрипта на сайте, серверного приложения с балансёром нагрузки и планировщиком, клиентов для службы поддержки и административных инструментов. И, что самое противное, со своих колоколен все будут правы.
                                                        «Фрукт — фрукт, сиська — сиська, цветок — цветок. То же самое, мать твою!» © «Чёрные паруса»

                                                        Этот конкретный пример говорит лишь о том, что предыдущий разработчик думал чем угодно, но не головой. Или вы рассказываете не всю правду, а лишь то, что вам выгодно. Ещё ни один программист не сказал, что транзакции и внутренние зависимости — это плохо. Они могут быть неудобными, долгими, сложными, но все альтернативы — хуже. Конкретно в этом примере есть две проблемы с транзакциями: не хранится отдельно таблицы с запросами на проведение операции, и нет реакции на провалившиеся транзакции (или, шире, нет поля результата запроса на операцию). Или оно есть, но его никто не пользовал. Но это уже другая история.
                                                        • 0
                                                          Напишите службу someservice.exe, оборачивающую some.dll в какой-то интерфейс хоть HTTP, хоть велосипедный, и вы получите сервис.

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

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

                                                          Таблица хранится, при успешном платеже формируется две записи — запрос на платеж с успешным статусом и собственно платеж. При неуспешном есть только запись в логе (реакция на ошибку).
                                                          • 0
                                                            Отлично, возражений нет. Тогда повторяю вопрос: о чём срач? Мы тут просто пожурчать собрались или ради дела? Если ради дела, то в чём вы со мной не согласны, когда я пишу «ничто не ново в этом мире» и «homo sapiens должен быть человеком разумным»?
                                                            • 0
                                                              Действительно концепция микросервисов не нова как явление. Просто дали сервисам с единственной ответственностью название «микросервис», чтобы подчеркнуть единственную ответственность в отличии от обычных сервисов, которые часто монолитно берут на себя решение множества проблем.
        • 0

          Капитан сообщает: надо сохранять id пользователя.

  • 0
    Т.е. то что в монолите можно было сделать в базе одним SELECT и где все проиндексировано, теперь надо делать 2 SELECT'a.
    А что если между запрашиванием списка френдов юзера и SELECT'ом постов, меня заблокировали, я получу публикации которые не должен был получить.
    • 0
      А что если между запрашиванием списка френдов юзера и SELECT'ом постов, меня заблокировали, я получу публикации которые не должен был получить.

      Вы получите публикации которые вы могли бы получить если бы запросили их секундой раньше. Это не проблема.


      Проблема будет, если запрашиванием списка френдов юзера и SELECT'ом постов другой пользователь сначала блокирует вас, а потом публикует что-нибудь. В таком случае вы можете получить публикацию, которой никогда бы не смогли получить при последовательном исполнении запросов.

    • +1
      Народная мудрость: лучше 5 быстрых селектов, чем один с многоэтажными джойнами, который может внезапно стать медленным и сложно-отлаживаемым.

      Потом эти же селекты раскидать на независимые сервисы, которые работают параллельно, отвечают асинхронно и склеить все в ноде.
  • –1
    Все намного сложней, по факту при использовании сервисов получаем распределенную и возможно децентрализованную сеть со всеми плюсами и минусами — аля (torrent, blockchain), но без готового механизма синхронизации, на данный момент этот механизм нужно «костылить подпорками», причем этого решение может быть архисложным, но думаю не долго и возможно совсем скоро один из cloud провайдеров, предложит своё «незаменимое», универсальное решение (сервис «шин» в принципе уже есть, но это не совсем то).
    И да, это скорей всего потребует или отказ от реляционных БД или их доработку, но думаю cloud провайдеры, предложат всем свою «суперудобную/масштабируемую» БД — по факту уже у них имеются, которая будет из себя предоставлять просто сервис.
    Вот такой вот новый, дивный мир cloud, посмотрим получится ли у cloud провайдеров и их инвесторов реализовать данную идею. И главную идею, загнать «овец» в свои cloud сараи.

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