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


Этап 4 — ненаучная фантастика.
Я вижу это на практике. Например, в Леруа Мерлен есть такая платформа.
А чем эта визуальная платформа лучше, нежели просто несколько строчек кода? Очередной BPMN — и как и та же Comunda — без программистов не работает.
Тем, что бизнес-процесс нужно осознать самому, передать знание другому и поддерживать и изменять. Сложные процессы осознать через код очень сложно, поэтому их всё равно рисуют, но без привязки к коду, поэтому такие схемы не точные и устаревают.
Я на нее намекнул в описании проблем в п.4, но это не всегда так. Бывает, что скатываются к монолиту, бывает, что нет. Всё зависит от уровня специалистов в компании.

Почему вы утверждаете, что монолит — это плохо и к нему можно только "скатиться" имея недостаточно хороших специалистов?

Я описал проблемы, которые возникают при монолитной архитектуре. Если для бизнеса они критичны, значит «монолит это плохо». Если для бизнеса эти проблемы не критичны, значит монолит это не плохо
Не совсем понятно как решились проблемы на этапе 2 Микросервисный монолит, при переходе к Микросервисам.
Архитектуру сложно понять и, чем больше сервисов вы добавляете, тем запутанней всё становится. В целом, добавление новых сервисов нелинейно повышает сложность архитектуры.

Добавили gateway, service discovery и чего? Архитектуру все также сложно понять. И от того, что сервисы вызывают друг друга через gateway с использованием service discovery линейности не прибавилось.
Что если на третьем микросервисе запрос завис? Что если там была ошибка? Что если на втором шаге должно было создаться сообщение в очередь, но оно не появилось?

И как нам тут поможет то, что мы делали в п.2.3? Предложенные паттерны (типа Circuit Breaker) могут помочь, но это большая и непростая работа по их внедрению и об этом ни слова.
При работе через API Gateway видно кто и как кого вызывает. Управляемость и наглядность повышаются в сравнении с беспорядочными запросами между микросервисами напрямую.

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

Порядка в запросах же не прибавилось. Если сервису А нужно вызвать сервис B, получить от него ответ, и в зависимости от ответа вызвать или сервис C или сервис D и опять что-то сделать, то вот вся эта цепочка останется и никуда не денется с гейтвеем или без. Чем тут gateway поможет?
Еще, нужно понимать, что делая gateway, вы создаете бутылочное горлышко по сути и вам его придется масштабировать. И тут уже без инструментов трассировки запросов не обойтись. А если применять инструменты трассировки запросов, то в принципе все равно что отслеживать запросы с гейтвеем что без него.
С точки зрения сервиса А действительно ничего не поменяется. Но представьте, что вам нужно понять, кто вызывает сервис А. Или нужно понять, где у сервиса А лежит API. API Gateway хорошо структурирует связи.
Или нужно понять, где у сервиса А лежит API

Не совсем понял что это значит.

API Gateway хорошо структурирует связи.

А также умножает кол-во всех запросов на 2…
не рассматривали для этого варианты с Service Mesh?
Используем или www.envoyproxy.io или сами пишем прослойки. istio.io пока не заводится в полный рост. В целом, концепция очень нравится.
«управляемость» не повышает потому что не появляется из воздуха и соответственно добавление прокси между вызовами само по себе управляемости не добавит.
Да и визуализация межсервисных вызовов- есть широкий ассортимент инструментов трассировки.
Не обязательно вводить доп.нагрузку и точку отказа для этого.

В остальном — судя потому куда ветер дует сейчас — в service mesh — это в некотором смысле происходит «под капотом».
А чем API Gateway помогает для улучшения наглядности? И так в любом логе или трейсинге видно, кто и кого вызывает. API Gateway для внутренних сервисов скорее усложняет отладку. Гораздо лучше API Gateway использовать для изоляции внешних запросов (для чего он обычно и делается).

Четвертый этап, который тут описан — это давно известный SOA, который провалился чуть менее, чем везде.

Из этой идеи мне не нравится:
1) Бизнес схемы. Сама механика использования бизнес схем — имхо, неудачная. Это выглядит красиво только на простых задачах, но превращается в ад, когда количество блоков в схеме приближается к 100, добавляются условные операторы, подобие циклов. Ни на один монитор это не влезает, поэтому начинают придумывать «группы блоков», которые можно свернуть/развернуть — но даже с ними быстро понять «код» — непросто. В классическом программировании уже давно этот вопрос решен: разделением на функции/классы ООП.
2) сама идея «программирования не-айтишниками». О нее уже многие набили шишки. Для не-айтишников приходится максимально упрощать апи, а для этого часто в жертву приходится принести производительность. Причем речь часто идет о потере производительности на порядки. А это быстро сводит на ноль идею масштабирования — ибо масштабированием мы пытаемся повысить производительность, а повышать ее перед этим убив в 10-100 раз — так себе идея.
3) отладка. В монолите мы ставим точку останова и смотрим, что передается. Легко по шагам проходим. Подобных инструментов для микросервисов пока не придумано. В микросервисах, я так понимаю, мы откатываемся назад в развитии средств отладки — по сути до «отладки принтом» — т.е. анализом километров избыточных логов, да еще и разбросанных по разным сервисам.
Логи должны быть аггрегированы в одном месте и связаны через CorrelationId. Не очень понятно в чем здесь идейная разница с монолитом
Идейная разница в том, что в монолите можно пользоваться отладчиком, а не только логами. Это в разы быстрее и удобнее.

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

Тестируемый код, хорошая архитектура и качественные логи — они всегда хороши. В любой ситуации.
Реальность же чаще такова, что есть код какого-то уровня легаси, часть из него вообще нельзя менять и где-то там произошел затык. И надо бы определить где и почему. И у меня стойкое ощущение, что с отладчиком это в разы быстрее, чем по логам. Просто потому, что (очень условно) отладчик позволяет «детализировать/обощать» информацию вплоть до функции. А с логами чаще всего в проектах лишь одна настройка уровня логов на весь проект. Бывает, что у каждого компонента своя настройка уровня логов, но я ни разу не видел возможностей задать для каждой функции свой уровень логов.

У вас потоки есть в монолите? Или всё в один ствол?
Принципиально, нет никакой разницы, монолит у вас с сообщениями между потоками или сервисы.
Что там, что там, дебажить что-то сложное будет одинаково трудно.
Что логи, что дебаггер будут влиять на поведение компонента, притом, логи в гораздо меньшей степени. Я вижу возможности делать разную детализацию логов для разных модулей даже в самописных логгерах, зачем гранулярность до функций — непонятно.

зачем гранулярность до функций — непонятно

Допустим, потому, что не все ф-ции pure и где-то она (ф-ция) "стреляет в колено" и нужно смотреть на то самое изменение состояния через дебаггер

Как это «нельзя задать для каждой функции свой уровень»? Любой log4j или аналог позволяет это сделать. Ну и можно фильтровать на уровне коллектора.
Я не то чтобы за микросервисы, но справедливость дороже.
что в монолите можно пользоваться отладчиком,

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

Отладчик на продакшене — ну-ну. А вот в тестовой среде отлаживать можно, только вот поведение может быть не то. Именно поэтому становятся популярны всяческие решения типа APM/tracing — они позволяют именно на продакшене отлавливать проблемы.

Отладчик на продакшене — ну-ну.

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

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

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

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

С чего это? А как они друг друга вызывают?
Вы же сами дальше пишете
позволяют увидеть кол граф между сервисами
Я имел ввиду, что можно увидеть все, что происходило в системе по определенному correlationId. Куда и какой запрос прилетел изначально, какие события он затригерил, какие доп данные из других сервисов были вытянуты ApiGateway-ем.
1) К сожалению, люди из бизнеса не могут заглянуть в код и порадоваться, что «классическом программировании уже давно этот вопрос решен». Использовать квадратики, когда их много тоже не очень удобно, но это всё равно удобней, чем вглядываться в кодовую базу сотни сервисов.
2) Вопрос производительности имеет место быть, но он решаем при грамотном проектировании.
3) Да, в монолите в этом плане намного проще :) Микросервисы добавляют сложности, как я написал, в обнаружении проблем и понимании как проходит запрос и какие события при этом создаются.

3). Не особо вижу отличий микро-сервисов от многопоточности в монолите. Если у вас в монолите асинхронное взаимодействие — ваши потоки фактически становятся сервисами. Да, разница может быть в том, что можно всех одновременно убить при ошибке, а так — одно и то же. Разве что, отладчику чуть проще работать в одном процессе, но это очень зависит.
Понимание логики и событий нужно и в случае монолита, при этом, как я уже писал, ошибка в его случае стоит гораздо больше, чем в случае микросервиса.

Микросервис можно раскатать на 150 машин и он будет работать быстрее, а в монолите рано или поздно будет достигнут предел вертикального масштабирования

Как будто монолит (с костылями и велосипедами) не умеет работать в распределенном режиме......

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

Ценность масштабирования сильно преувеличена — как примеры:


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

Конечно, можно двигать в облако… но это реально дорого. И все равно софт к этому должен быть "готов"

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

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

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

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

Статьи по запросу «scale up scale out comparison» говорят об обратном. Если коротко, то супер-машина с 100ГБ оперативки стоит дороже, чем 10 машин с 10ГБ оперативки

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

Чем в вашем представлении отличается приложение, которое решает одну бизнес-задачу от микросервиса?

Если приложение решает одну бизнес-задачу (соответствует SRP), то оно и есть микросервис
В целом это хорошее отделение, но стоит уточнить:
Приложение пилит одна команда. Приоритеты по развитию приложения определяет один человек.
Сложность при переходе на микросервисы никуда не девается, она просто переходит в отладку и мониторинг, поддержку и эксплуатацию.
Иллюзия дешевизны и простоты испаряется при начале эксплуатации, поиске кадров и координации разработки при выкатке разных версий микросервисов.
Иллюзия дешевизны и простоты

Это ошибочная иллюзия. Если у бизнеса есть цель уйти от проблем монолита, то за это придется платить. Тут дело в том, что если ваши конкуренты смогли перейти на микросервисы и получить ускорение, то вам тоже придется это сделать, потому что захочется не отставать в скорости.
Иногда нужно задаться вопросом: а зачем разбивать монолит и плодить DevOps?
Может обычный decoupling достаточен?
Зачастую продукту и не требуется горизонтальная масштабируемость (нагрузки небольшие) и микросервисы не выгодны как архитектурное решение для поставленной задачи.

В зависимости от взаимодействий отделов, другой отдел вполне может использовать либо коробочное приложение 3-ей фирмы, либо создать другое самодостаточное приложение.
Главное, чтоб решало задачи, выдерживало пиковые нагрузки, интегрировалось и могло прорабоать х лет без серьезных вложений в доработку и обслуживание.

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

На случай pushback: 25+ лет использую разные архитектуры для разных задач, включая описанные автором решения.
Суть: разным задачам разная архитектура.
Я согласен, что делать микросервисы ради моды нет смысла, потому что такая архитектура дороже в реализации и развитии
Во всех архитектурах микросервисов и подобных решений не хватает дополнительных метрик связанными с жизненными циклами бизнес логики. Нужно понимать, что сформировавшийся логике легче может жить в вакууме, чем новым идеям, которые могут переписываться хоть каждую неделю.

В своей практике делаю два условных слоя: Сервисы и Бизнес логика. Также есть их этапы эволюции:

1. Монолит. Сервисы отвечают за свою предметную область и вначале предоставляют просто CRUD, Бизнес Логика же использует эти сервисы под свои потребности. Если бизнес логика повторяется в нескольких местах, то я оставляю дубликат кода, так как логика может поменять в одном из мест достаточно быстро.

2. Монолит. При формировании уже устойчивой бизнес логики можно анализировать дубликаты кода для определённой предметной области и выносит в соответствующий Сервис. Тем самым мы уменьшаем код в Бизнес Логики и начинаем наращивать сервисы устойчивой логикой уменьшая вариативность их использования.

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

Описанный выше подход не использует триггеры и эвенты, Сервисы не общаются между собой никак, вся логика вызовов строится внутри Бизнес Логики, на то это и оркестрация. Если посередине Процесса-1 одного сервиса нужно вызвать Процесс-2 другого сервиса, то Процесс-1 просто разбивается на два отдельных Процесса и Бизнес логика вызывает их по порядку передавая данные между ними.

Также это очень хорошо ложится под паттерн Saga и вопрос с распределёнными транзакциями.

P.S.
В 2012 году наткнулся на блог Александра, даже задавал вопросы по архитектуре, состоял в .net рассылке. Спасибо большое, Вы внесли большой вклад в моё развитие. Рад, что спустя такое количество времени нахожу общие идеи и могу понимать все эти решения.

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


P.s. Рад, что как-то вам помог :)

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