Pull to refresh

Comments 105

И наступает время деплоя. И тут, вам придётся аккуратно последовательно отключать все ваши микросервисы и накатывать новые версии.

Вы все еще катите руками?

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

На единственном сервере

Ну тогда полностью согласен — Вам не нужны микросервисы.

Да, именно. У автора похоже "расспределенный монолит", деплой в продакшен раз в месяц и недопонятые преимущества микросервисов.

А ничего что на микросервисы бизнес тратит уйму денег на отдел DevOps? А ничего что бизнесу приходится придумывать компенсационные механизмы, так как с ACID настоящий гемор. И еще куча недостатков.
Вообще тема религиозная, но хайп вокруг микросервисов есть и чаще они применяются в тех местах, где создают только проблемы
А какое отношение DevOps отдел имеет к микросервисам?
Девопс работает с тем что есть. И неважно это монолит, сервисы, микросервисы.
Важен размер всей инфраструктуры и сложность пайплайнов.

Простые 10 микросервисов сделанные под один грамотный шаблон (что зависит от архитектора и техлида, а не девопса), которые собираются, тестируются и деплоятся на 1-2 енвайрнменте с простыми релизами раз в месяц/квартал — можно вообще без девопса справиться, или один девопс может таких проектов десятками один раз настроить и почти не заглядывать. А может и какой-нить разработчик один раз настроить.
Говорить что микросервисы=девопс или agile — некорректно.
А какое отношение DevOps отдел имеет к микросервисам?
Девопс работает с тем что есть.

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

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

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

Очередной пост в котором противостояние "монолит против микросервисов". А надо — "сервисы против микросервисов". Но слово "сервис" слишком простое для buzzword, так что надо всегда говорить "hyper-convergent micro service".

Просто "сервисы" включают в себя микросервисы. Между этими понятиями сложно провести какую-то границу. Общий смысл такой, что не надо дробить функциональность на сервисы слишком мелко, иначе будет сложно, долго и дорого.

Ровно так же можно утверждать, что монолитное приложение со встроенной базой данных и веб-сервером — это вариант микросервиса с кардиналити 1. Формально — да, фактически, извращение идеи.


Микросервисы от сервисов различаются подходом к архитектуре взаимодействий. На сервисы выносятся куски исходя из внешней логичности (data locality, proximity) или целей резервирования, на микросервисы выносятся куски кода исходя из финансовой мотивации сдать на программирование джуниорам/аутсорсу и изоляции от криворукости оных за счёт сетевого контракта.

проверяем идею — взлетела или нет. А уже потом думаем, переписывать на микросервисы или нет.

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

"Потом" наступит, но со временем, только когда это будет оправдано экономически.
Тут нужно искать баланс между стоимостью разработки и поддержки. Если стоимость поддержки становится высокой, то руководитель разработки или тимлид сможет прийти к бизнесу и получить для команды время на рефакторинг. Главное — перевести сложность поддержки в понятные бизнесу метрики: Time-To-Market, например.

только когда это будет оправдано экономически.

«Пока ты тут будешь свой код рефакторить — конкуренты выкатывают новые фичи».
«Зачем тебе рефакторить? Ты плохой программист и написал говнокод?»

Да у бизнеса бывает сотня отмазок почему время рефакторинга — это впустую потраченное экономически время. TtM считается в попугаях, нельзя сказать что еще месяц и всё. Нет точных метрик — нет санкций.
Когда пилят новый модный стартап, ещё не понятно из каких подсервисов надо делать готовый продукт, но любители микросервисов, которые не могут отказаться от этой идеи начинают дробить продукт на микросервисы попросту на угад. При этом спорят по пол дня сколько тут надо микросервисов сделать 4 или 6.
В результате такого искусственно деления получается реальный говногод. Обычно в этот момент «команда удачи» успешно увольняется.

Ну, а рефакторинг это ежедневная работа, запилил задачу, немного прибрался. А не какая-то супер таска на 1 месяц.
Когда пилят новый модный стартап, ещё не понятно из каких подсервисов надо делать готовый продукт, но любители микросервисов, которые не могут отказаться от этой идеи начинают дробить продукт на микросервисы попросту на угад. При этом спорят по пол дня сколько тут надо микросервисов сделать 4 или 6.

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

Ну, а рефакторинг это ежедневная работа, запилил задачу, немного прибрался. А не какая-то супер таска на 1 месяц.

Разбитие монолита на отдельные куски(или уже тем более микросервисы) это не то чтобы тривиальная задача. И даже не то чтобы обязательно решаемая. Ну в том плане что часто будет дешвеле/быстрее просто взять и написать всё заново.
Структурировать код внутри папок/директории файловой системы (код, который скомпилируется в один бинарь), это не то же самое, что и структурировать код среди приложении, разнесенных по сети и возможно запускаемых на разных машинах.

Я не знаю, но лично для меня "структурирование кода внутри папок" без "логического" структурирования не особо имеет смысл.

И в любом случае это не "дробление наугад" как было написано выше.

Ну в том плане что часто будет дешвеле/быстрее просто взять и написать всё заново.

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

Вообще, «с нуля» если делать правильно то это новая команда (вторая), которая соревнуется с первой кто лучше. И 2 независимые версии того что переписываем. И 2 команды тестирования. И так далее. В общем, «переписать с нуля» можно например emacs, но крупный портал сходу точно не выйдет, это дело может легко несколько лет занять.

Переписывать можно по частям, одновременно работая в двух системах, маршрутизируя запросы юзеров между ними

«Пока ты тут будешь свой код рефакторить — конкуренты выкатывают новые фичи»

Если не отрефакторим, то фичи мы будем выкатывать медленнее конкурентов — они явно времени на рефакторинг не жалеют )


«Зачем тебе рефакторить? Ты плохой программист и написал говнокод?»

Ты плохой постановщик и 5 лет назад описал только 5 фич, а сейчас жалуешься, что 100500-ю никак закончить не можем без багов — надо было сразу все 100500 описать ))

недавно была вполне внятная статья TuTu.ru о постепенном переходе от монолита к микросервисам и экономической обусловленности перехода. Кажется, вполне разумный подход.
Оправданное экономически «потом» может наступить только в одном случае — когда текущее положение вещей настолько хреновое, что стоимость поддержки становится запредельной и съедает всю прибыль. Но тогда вообще уже поздно пить боржоми, поскольку почки уже отвалились.
В итоге монолит обрастает функционалом, костылями и со временем превращается в макароны.

А микросервисы каким-то магическим образом защищены от костылей и плохого кода?

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

Впрочем, разработка с горящими сроками никогда ни к чему хорошему не приводит.
Впрочем, разработка с горящими сроками никогда ни к чему хорошему не приводит.

Золотые слова, Юрий Бенедиктович (с) Наша Раша
Эти бы слова — да нашему тимлиду в уши.

Думаете тимлид сроки назначает?

монолит обрастает функционалом, костылями и со временем превращается в макароны

И микросервис легко превратить в ball of mud. Для избежания сего индустрия придумала: tdd, solid, patterns, ddd, layers, oop и еще кучу всего. Если команда не умеет писать монолит, то в микросервисы лучше не лезть.

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

Микросервис не так страшно отдать команде, которая не умеет писать монолит как монолит )

при условии что есть подробные юнит и интеграционые тесты, написанные основной командой которая всё умеет (!) и есть чёткое апи. Тогда да, можно отдавать микросервисы индусам и студентам. Но остаются тесты на уязвимости ещё, и желательно чтобы это не были критические микрсервисы…

ЗЫ без возможности отключать и удалять тесты, а то бывало и такое — новый код не проходит тесты? Удаляем тесты. Максимум — временное отключение отдельных тестов и без возможности выкатки итога в прод.
если видеть что «вроде выстреливает» и вовремя начать работу на деление — то это повернуться к соседнему столу «Вась, давай платёжный модуль вынесем отдельно, ты же его сделал, пойдём пообедаем и накидаем схему апи, которое ты быстро сделать можешь». И уже через несколько дней будет раскатана версия с апи. Да, это будет версия 0.1, которую потом ещё не раз отрефакторят, но пока продукт РАЗВИВАЕТСЯ это делается несложно (учавствовал в подобных процессах). Если это уже выстрелившее решение с большой базой юзеров, там так нельзя и нужно «энтерпрайзно» делать, дорого и долго. И что в небольшой команде решилось за пол часа, будет делаться месяц… тоже проходил в госкомпании, «нарушил субординацию» и решил с соседним отделом напрямую за пол часа, за что получил выговор, надо было через начальство, бумажки и месяц+.
сейчас тренд уже не микросервисы — а лямбды.
Стоит разделять понятие «монолита» и приложения на единой кодовой базе

«Монолит» является анти-паттерном: синонимом "легаси", плохо спроектированного, сильно и неявно связанного, не тестируемого приложения

Single-repo приложение может быть хорошо спроектированным, тестируемым, модульным, слабо связанным, легко расширяемым
Что такое «приложение на единой кодовой базе»?
Составные такого приложения могут стартовать самостоятельно или имеется ввиду что-то типа DDD с одной точкой входа/старта?
Если говорить о бэкенде/десктопе:
одно приложение на один бизнес-проект; в одном репозитории; написанное на одном языке программирования.

Точек входа может быть много, как и окружений, как и собранных бинарников
«Монолит» — никак не связан с плохо, неявно или чем-то еще. Это просто тип архитектуры приложения. Все. Превратится ли монолит в плохое, неявно связанное и нетестируемое легаси зависит от того какие решения будут приниматься в процессе развития и насколько профессиональны были разработчики что это писали.
Из википедии "Monolithic system":
A software system is called «monolithic» if it has a monolithic architecture, in which functionally distinguishable aspects (for example data input and output, data processing, error handling, and the user interface) are all interwoven, rather than containing architecturally separate components.

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

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

Ну это утрированно.
Монолит может иметь очень хорошую врнутреннюю структуру и модульность, но всеравно будет оставаться монолитом со всеми вытекающими недостатками. Основной из них это то, что через CI/CD pipeline тоскается монстр и в него все интегрируется на каждый чих.

Если таскать через CI/CD аналогичные по суммарному объёму кусочки монстра — процессорного времени сборщиков будет израсходовано сильно больше, если учитывать все дополнительные расходы на сбор контейнеров, pre/post действия. И суммарный объём — это в идеальном случае; в реальности микросервисы часто дублируют функционал друг друга, так что кода в них оказывается больше, чем в single-repo приложении, даже если они идентично повторяют бизнес-логику последнего
Нужно учесть, что разные кусочки монстра могут иметь (а скорей всего и имеют) разный релизный цикл. Что-то релизится по 10 раз на день, что-то раз в сесяц, а что-то вообще не меняется никогда. В таком случае с кусочками мы имеем выгоду. Нам не нужно собирать огромного монстра, чтоб зарелизить его пятку.

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

Обратите внимание, что в упомянутой статье ссылаются всего на один источник. Хотя казалось бы это одно из фундаментальных определений и пруфов должно быть миллион.
Данное определение мне кажется как минимум странным, если не вовсе ошибочным.
При этом в статье en.wikipedia.org/wiki/Monolithic_application все более-менее адекватно. Может быть есть какое-то принципиальное различие между понятиями system и application, которое вызывает такое разночтение.

Если монолит - это отсутствие слоев, структуры, инверсии зависимостей и проч, то как тогда называются приложения со слоями, структурой, из, но огромных размеров?

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

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

Такое ощущение, что все вменяемые архитекторы вымерли, а им на смену пришли вчерашние джуны, которые не могут в голове удержать больше чем 3 ендпоинта и 2 аргумента.

Я уж не говорю о том, что обеспечение reliability всего этого зоопарка требует целого нового квалифицированного отдела внутри компании.

В командах на 1000+ человек? А на 100+?

> А когда микросервисы — это хорошо? — Когда у вас несколько команд, которые независимо делают разные компоненты сервиса.

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

Тут основные плюсы с точки зрения процессов это независимый деплой (проще тестировать и выкатывать/откатывать по кусочкам) и гарантия того, что другие команды не сунутся туда, куда им соваться не нужно, и не будет конфликтов при мержах (изоляция), также форсируется общение через чётко документированное API (нельзя взять и накостылять что-то в обход). Когда над монолитом работают несколько команд, постоянно что-то отваливается/не собирается, нужно разруливать какие-то конфликты при мержах, другая команда залезла в твой код и накуролесила, поменяли общий класс-зависимость и поведение немного поменялось, но сломало твои кейсы и т.д. (это даже при DDD). С микросервисами вообще в этом плане лепота - присутствует какая-то стабильность, при переходе от задачи к задаче и мержах старых задач есть уверенность, что оно с вероятностью 99.99÷ заведется без проблем и будет работать так же, как в прошлый раз оставил

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

>Если команда владеющая библиотекой может «внезапно» поменять АПИ своих интерефейсов то также внезапно она может поменять и свой протокол.

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

DLL hell - абсолютно такая же проблема, поэтому и придумали версионирование. Изменение затрагивают только одно приложение (модуль) и не имеет полномасшатбных изменений по всей системе. Старая версия библиотеки будет продолжать работать как и раньше, пока её не обновят в отдельно взятом микросервисе.

>Библиотеки никто не отменял.

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

Если такие проблемы есть, то это либо проблемы архитектуры, либо её понимания.

Одновременно раные версии одной библиотеки в рамках одной сборки не используются точно так же как одновременно не вызваются разные версии API одного и того же микросервиса. А в рамках разных сборок использовать разные версии библиотек и проблемы нет. Разные версии библиотек существуют точно так же как и разные версии API микросервисов.

Только с библиотеками у нас есть возможность проверки совместимости через статическую типизацию и явное отслеживание минорных изменений в библиотеках. А микросевисные API версионируют максимум major версию, по факту делая что угодно внутри. Если что-то сломалось на этапе компиляции из-за обновления общей зависимости — это лучшее, что может случиться с продуктом и к этому надо стремиться. С микросервисами выявление проблем уходит в runtime.

Приведённая мотивация «плюсов» микросервисов является притянутой за уши. Это скорее их минусы. У них есть безусловные плюсы, но они совсем в другом.

>точно так же как одновременно не вызваются разные версии API одного и того же микросервиса

Вполне вызывают при rolling release или canary-релизах, когда одновременно разные инстансы ссылаются на две версии API

См. комментарий выше про DLL Hell

разные инстансы

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

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

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

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

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

Да вполне естественно, когда в новую версию API добавили нужную фичу, при этом сильно изменив и всё остальное типа протокола или формата, а времени переписывать весь клиентский код сразу нет. "работает — не трогай" — вполне естественно. Вот и появляются в коде других микросервисов и пользовательских приложений ServiceAClientV1, ServiceAClientV2 которые для разных частей одного инстанса обращаются к другому инстансу по разным версиям API. И это может длиться годами пока команда сервиса A не продвинет выделение времени другим командам для выпиливания ServiceAClientV1 из кодовой базы других команд, потому что все время в А уходит на согласованную поддержку двух версий

Да вполне естественно...

Вы путаете семантическое и фактическое версионирование.
Вы говорите о первом, а я о втором.

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

А семантическое версионирование V1, V2 и т.д. ничем не отличимо от создания новых роутов(оно им и является), и по факту является надёжным механизмом непрерывной эволюции систем, что вполне естественно.

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

Принципиальной разницы между случаями нет — и то и другое это просто common sense в управлении изменениями.

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

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

Хотя по хорошему надо думать не как сделать «всё красиво, как у больших дядек» будучи маленькими, а том «как мы будем превращаться в больших по мере роста, если он будет».
Если будет рост, то неизбежно и будут ресурсы масштабироваться.
На мой взгляд, все принципы программирования не про то «как всё правильно сделать один раз», а о том «как правильно сделать, чтоб можно было измениться не один раз».
Как и в любом деле — преждевременная оптимизация это так-же плохо как и ее полное отсутствие. Когда проект не вышел еще даже из стадии «а давайте посмотрим что будет если..» закладывать в него возможность расширения до масштабов поискового сервиса Гугла — это означает гарантированно убить его еще на стадии зародыша. Команда начинает вместо того что-бы решать реальные насущные вопросы проекта бороться с надуманными проблемами, которые «может быть, возникнут в далеком будущем, если проект выстрелит».

Тут ещё конфликт интересов может быть почти всегда есть на разных уровнях Кому-то интересно попробовать в проде новый технологии и подходы, кому-то наоборот неохота изучать что-то новое и переделывать на него без явной необходимости. Даже у бизнеса бывает мнения типа "если мы не будем использовать стандарты де-факто типа кубернетес, то не получим инвестиции на рост"

Одновременно раные версии одной библиотеки в рамках одной сборки не используются

Привет от экосистемы nodejs

Ну транзитивные зависимости обрабатываются преимущественно корректно, а за peer и прямыми нужно внимательно следить. От того, что технически что-то можно сделать — совсем не значит, что это нужно делать практически. Выстрелить себе в ногу запретить сложно.
Во многом согласен с автором. Но всё же главное проблемой микросервисной архитекутры является соблюдение косистентности.
Давайте честно, *большинство* микросервисов пишется без какой-либо оглядки хотя бы на идемпотентность, не говоря уже о согласованном откате, «если что-то пошло не так». И тут нет исключений. Я это видел даже в Яндексе, хотя вроде как и собеседуют сильно, но на деле все пишут кучу микро-какашек.

Оставаясь в вашей терминологии:
микрокакашки когда они становятся критическими, куда проще выкинуть и заменить на менее пахучее, чем одну большую, размазаную на весь бизнес много лет назад.
Чувствуете разницу? ;)

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

или другой вариант: бездумный retry, когда на любую ошибку выполняется повтор, без вникания в то, как его правильно и допустимо ли делать.

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

Ну а как научиться, не начав делая их неправильно? ))

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

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

Я бы добавил еще следующие плюсы-минусы микросервисов.
Плюс:


  • (на мой взгляд) Легче держать в голове 10 маленьких микросервисов, чем одно огромное приложение.

Минус:


  • Запуск микросервиса — это, по-хорошему, запуск приложения, для которого нужно применять процесс Launch Readiness Review (в разных компаниях называется по-разному, но не суть), и запуск из 2-3 дней превращается легко в 2-3 недели. Хотя это недостаток относительный.
нам приходится разрабатывать протоколы общения микросервисов, а составить хороший протокол — это отдельная сложная задача.

дык берите уже готовые решения, не?

Скорее имеется в виду прикладной уровень, типа OpenAPI документа

Микросервисы это всегда про масштаб — масштаб проекта, масштаб команды, масштаб нагрузки.

Если масштаба нет, то да, микросервисная архитектура обойдется просто большим объемом кода и раздутой сложностью проекта.
Как ни странно, основной аспект применения микросервисов всегда игнорируется. Не столько важна сама по себе модель архитектуры, сколько скорость изменения бизнес-модели продукта. Чтобы быстрее изменять бизнес-модель, вам нужно разрабатывать большим количеством команд в разных стеках — микросервисы. Быстрее доставлять изменения в продакшн — микросервисы. Быстрее и гибче масштабироваться под изменяющиеся требования (scaling) — микросервисы. Теперь перечитайте — и станет понятно, что микросервисы чаще всего не нужны на старте продукта. Миллионы статей на тему «Мы забивали гвозди, теперь закручиваем шурупы отвертками», «Не используйте шурупы там, где можно забивать гвозди молотком», «Не забивайте шурупы молотками» имхо более чем бесполезны. Важно делать все осознанно, понимая, зачем, что, и когда нужно.

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

микросервисы чаще всего не нужны на старте продукта

На старте продукта в лучшем случаи есть одна команда. В худшем - два с половиной человека. Зачем им на старте микросервисы?

Отдать на аутсорс всякое не особо на старте важное, но необходимое?

>Теперь перечитайте — и станет понятно, что микросервисы чаще всего не нужны на старте продукта.

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

конечно есть. И есть две разумные причины для старта на микросервисах — 1) разрабатывается новая версия продукта 2) сознательно исключены риски того, что продукт не взлетит и есть потребность в уже долгосрочном решении.
По опыту работы в реальном времени (QNX) мне всегда казалось удобным делать все именно в микросервисах, так гораздо проще настраивать и соблюдать время исполнения
Довелось работать в одной фирме, в эдаком внутреннем стартапе внутри большой фирмы — там пилили проект под внутренние нужды с прицелом на то что-бы продавать его позже во внешний мир. Проект так и не вышел на стадию реальной эксплуатации за тот год что я там проработал, зато микросервисов на нем наплодили… не соврать, с пару десятков точно было. При том что данных в них крутилось с гулькин хрен, если взять все данные всех сервисов, то там и гигабайта не набиралось.
И до сих пор помню как там геморройно было делать какие-то более-менее крупные фичи, помню пилил небольшую фичу, которую на монолите я бы за неделю сделал, не особо напрягаясь (несколько таблиц в БД, круд и апи для фронта), я там месяц фигачил, сделал штук шесть БД в общей сложности, пару-тройку микросервисов, и кучу протоколов обмена между ними, потом все это долго и нудно отлаживал.
С одной стороны это было весело и познавательно, с другой — когда с той фичей закончил и на горизонте замаячила другая такого-же рода, я крепко задумался, и решил, что ну его нахрен — новых знаний и умений мне это не принесет, а ковыряться снова со всем этим вот не хотелось совершенно.
На старте проекта монолит прекрасно может быть надёжно декомпозирован внутри кода даже между между разными независимыми командами через разработку отдельных пакетов (npm-пакет, jar, dll и т.д.) и впоследствии декомпозирован на реальные микросервисы.

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

Впоследствии, монолит на таких принципах достаточно легко естественным образом по мере эволюции системы преобразуется в микросервисы, переносом исполняемого кода библиотек «my-lib» в отдельные процессы(микросервисы) «as-is» и реализацией нового пакета «my-lib-client» с идентичным интерфейсом, реализующим уже только удалённые вызовы.

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

Резюмируя.
Архитектуру проекта можно реализовывать так, чтоб на одной и той же кодовой базе, в любой момент времени можно было двумя разными CI-pipeline собрать две разные версии продукта: (1) монолит, все сервисы которого работают на одном хосте в рамках одного процесса; (2) набор микросервисов, работающих на разных хостах и взаимодействующих друг с другом по сети;

Спор, «монолит VS микросервисы» глупый. При адекватном подходе можно иметь и то и то в зависимости от ситуации.
А вы можете привести пример, как реализуется асинхронность на архитектурном уровне между библиотеками? Именно об этом хотелось бы узнавать из таких вот статей, а не подпитку для холиваров читать. Получается необходимо, чтобы сервис из библиотеки имел метод для приема задания, куда-то его складывал, а потом куда-то отстукивал с колбеком? Или как это будет по факту с библиотеками? Те же брокеры сообщений или как-то проще можно поступить?
Это не так важно и зависит от конкретной реализации. Если нужны очереди, то хоть локально, хоть удалённо, а как-то и где-то их надо по-любому реализовывать. Искусственно городить огород только ради асинхронности нет никакого смысла. Асинхронность интерфейса может быть и номинальная.

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

Этот convention даёт возможность сразу же писать код как проще и быстрее в самой библиотеке не плодя преждевременно сущности в виде новых микросервисов без необходимости, а при появлении этой необходимости — относительно безболезненно перенести его в другой проект.

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

Пример из реальной жизни:
(1) Был сервис 'svc1' и библиотека 'my-lib' с некоторым функционалом.
(2) При появлении необходимости, создали другой сервис 'svc2', в который перенесли весь функционал(просто подключив библиотеку к другому проекту), переименовав библиотеку в 'my-lib-impl' и выставив наружу сетевой интерфейс библиотечных функций.
(3) Реализацию 'my-lib' заменили на сетевые вызовы к 'svc2' и 'svc1' по прежнему ей пользуется не особо делая различие, что вызов методов библиотеки уже стал сетевым.
Абстракция через интерфейсы понятна. Но чтобы реализацию интерфейса вынести можно было в удаленный сервис, значит эта реализация должна быть полностью независима со своим доменным контекстом и своими сущностями. Эти контексты необходимо как-то синхронизировать. Плюс асинхронные вызовы подразумевают наличие какого-то посредника, через который можно получить ответ. Это получается тот же микросервис, но физически в одном монолитном проекте. Вы об этом?

Просто судя по комментариям и холиварам в сети о микросервисах, основные претензии как раз затрагивают неудобство такой вот работы. И в целом без разницы — в одном это процессе работает или в разных.

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


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

Однажды работал на проекте (фронт), где некоторые части были вынесены в отдельные npm пакеты — типа своей библиотеки компонентов (вернее, своих костылей над primeng). В абсолютном большинстве случаев при изменении чего-то в одном из приложений, которые эту «библиотеку» использовали, требовалось редактирование самой библиотеки. Что естественно приводило к поломкам в других приложениях.

А другие приложения бездумно обновляли версию этого пакета?

Люди наивно полагают, что делать много простых маленьких микросервисов вместо одного большого сложного монолита проще. Но это конечно враньё. Внутренняя неустранимая сложность решаемой задачи просто уходит с отдельных элементов и ложится... на что? Куда-то с глаз долой на протоколы взаимодействия и, хуже того, на орг.процедуры управления изменениями. То есть там, где мы с монолитом имели кошмар, с микросервисами мы имеем сущий адъ.

Это смотря какие "мы", на каком уровне "мы" и тп. Жизнь "нас", команды разработчиков какого-то модуля монолита, часто становится проще, если принято решение вынести его в микросервис. По крайней мере никто не завяжется на наши детали реализации: вот наш ендпоинт, вот его контракт, вот даже клиентская библиотека, и больше у вас ничего нет физически.

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

В природе всё просто — есть задача и нужно её решить в рамках имеющихся ресурсов. И всё. А микросервис или монолит выйдет — природе плевать. И бизнесу тоже плевать, правда лишь до той поры, пока среди начальства не объявится молодой гений, почитавший набор рекламных статей, в том числе на хабре. Ну и тогда начинатеся…

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

Хотя в бессмысленном «деле» (ака «бизнес») чем же ещё заняться? Ну конечно — тем, что душе приятно, то есть пофлудить, обсудить, ну и ни к чему не прийти в итоге. Зато как приятно!
Понятно, что есть плюсы и минусы. Так-то на каждый ваш пункт можно сформулировать контр-аргумент.
На мой взгляд, смысл микросервисной архитектуры некорректно понимают даже многие из тех, кто ее якобы использует.

Сначала я опишу то, что часто считают проблемами микросервисной архитектуры:

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

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

2. Микросервисы сложно обновлять, так как всю систему нужно «остановить». Это тоже является следствием некорректного формирования зависимостей между функциональными сущностями (собственно, микросервисами). Все это имеет одну и ту же природу — большинство разработчиков не понимает сути декомпозиции.

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

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

Иными словами, сложность обновления — это не свойство микросервисной архитектуры, это свойство топологии связей частей целого, выбранное таким образом, что консистентное мгновенное состояние системы оказывается зависимо от неконсистентности (разнесенном во времени и/или пространстве запуске) микросервисов.

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

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

3. Энтропия. Фактически все минусы возникают в неосознанном и неумелом контроле энтропии в системе. Ее «утечка» происходит, либо в меру нелинейного роста сложности топологии при неосозанном подходе к декомпозиции (так как степень свободы в топологии растет в общем случае квадратично N^2, а конфигуративное множество — факториально, следовательно редукцию делать все сложнее), либо в меру вытеснения в мета-конфигурации (вытеснение конфигурирования частей системы в рантайм — фактически это так называемая проблема интерпретации в контексте нейросетей), создает ощущение «минусов», либо очевидные с практической точки зрения ограничения. Но все эти минусы и ограничения — это следствия малой степени осознания процесса управления сложностью (контроль энтропии).

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

Так в чем же сакральный смысл микросервисов?

Сутью микросервисов является намеренное и осознанное абстрагирование функциональной сущности от «канального уровня» передачи сообщений.

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

Да, вы можете намеренно внедрить в систему консистентность глобального состояния путем внедрения кворума на синхронизацию, тем же блокчейном (как классом взаимозависимости в данных), или создать систему с высокой степенью синхронизации по времени, но сам факт консолидации состояний при декомпозированном дизайне обладает стоимостью на сериализацию + синхронизацию (выборы, кворум). Вы должны четко понимать, зачем вам это нужно, почему вы это делаете, готовы ли вы заплатить стоимость такого latency, не станет ли сам факт синхронизации бутылочным горлышком системы. Вы должны четко понимать, какие свойства для вашей системы целевые, иначе это басня Крылова «Мартышка и очки».

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

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

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

Иными словами, микросервисная архитектура позволяет создавать масштабируемые системы (любого масштаба), которые пытаются «скальпировать» реальность с минимальным latency, но лишь при условии, что создатели осознают высокую стоимость сериализации на передачу сигналов, а также зависимость между стоимостью сериализации и степенью параллелизма, которые и формируют сходимость системы к некоторому минимальному latency в процессе проекции асинхронных потоков в глобальное состояние (в global state — с точки зрения понятия statefull, что упрощенно можно представить как некий консолидированный map-reduce по всем данным, или «отчет»), которое в свою очередь будет консистентно на момент времени t-1, но в настоящий момент времени будет оставаться принципиально неактуальным по аналогии с вашим намерением прокрутить скролл на странице с самим фактом прокручивания и наблюдением результата в меру latency на «сериализацию» данных через органы восприятия.

Все мы интерпретируем «прошлое», считая его актуальным настоящим. Это лишь вопрос масштабов времени. Для коммерческих систем реального времени необходимость реагировать быстро эквивалентна инстинкту самосохранения.

P.S. На правах моего субъективизма.
Микросервисы сложно обновлять, так как всю систему нужно «остановить»

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

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


Иными словами, сама формулировка об остановке противоречит, как Вы правильно указали, свойствам микросервисной архитектуры.

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

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

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

А если пытаться выразиться в контексте проекций Футамуры — то микросервисная архитектура — это специализация топологии энтропией ^_^
Микросервисы — это когда мы можем запустить новые версии и в зависимости от вида переключения (canary, blue-green) или сразу весь трафик перекидываем в новую выкатку, при этом старый работает и готов опять принимать, или закидываем например 5% трафа. При этом нужна определённая гибкость, в частности обновления бд должны уметь работать в +-2 версиях выкаток, что иногда требует длительной подготовки выкатки, но само переключение по максимуму прозрачно для пользователя. А монолит это почти всегда «окна обновления» с остановкой сервиса.
Я бы все-таки отметил, что, когда речь идет о процессе обновления (то есть о состоянии системы в динамике), то речь именно о предметной области обновления (это отдельный домен в DDD) при сохранении функциональной корректности.

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

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

К чему это я — нет я не оспариваю истинность ваших утверждений (я вообще никогда ни с кем не спорю, так как в этом просто нету смысла), но я пытаюсь отметить (для понимания читателей), что многие ошибки, парадоксы и противоречия (противоречие единого состояния и декомпозиции) возникают там, где нету четкой границы между предметными областями (там, где мы плохо провели границы или не провели их вовсе). Иными словами там, где выделено недостаточно независимых слоев абстракций в представлении системы. Словно система как единое целое представлена недостаточно точно, и эта «неточность» формирует излишние свободы для holy war'ов.

Фактически все статьи вида «что такое <тут любая сущность>?» порождают каскад обсуждений вида дифференциального сравнения свойств двух подмножеств одного семантического множества — именно поэтому спор (дифференциальное сравнение) смысла не имеет, так как несет в себе функцию поиска отличий, вместо процесса классификации (формального определения границы между классами — то есть решение задачи непротиворечивого представления системы в виде набора предметных областей с полным покрытием).

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

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

Это вообще слабая сторона в формализации систем (в их полноте представления и непротиворечивости модели).

P.S.
Если не совсем понятно то, о чем я пишу, то я попробую объяснить простыми словами:

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

Если мы поставим вопрос о том, что такое «самолет», то фактически вопрос будет слишком абстрактным, но тем не менее, этот термин (класс систем) обладает определенными характеристиками (свойствами).

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

— Есть ли у самолета шасси?
— Да есть.
— А что если мы шасси во время полета внутри фюзеляжа поменяем на другие?
— Ну, они должны быть совместимы, иначе посадка будет непредсказуемой.
— Хорошо, они совместимы.
— А что если мы будем менять их поочередно, а не одновременно? А что если бы была возможность заменить один из двигателей на ходу? Или вообще изменить геометрию самолета?

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

Иными словами свойства шасси, их состав, их характеристики, даже их динамика или их замена в динамике не имеют отношения к классу систем — самолет. Хотя бы потому, что есть самолеты с посадкой на воду…

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

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

Такова наша природа) Простите за «многабукф», мне бывает интересно порассуждать)
Есть ситуации и приложения, где МС не нужны. Но если вам нужен ХА, то забудьте про АСИК и монолиты.
Куча контор думают, что возьми динозавров, которые ничего кроме монолитов не делали и дай им задание, то они, без опыта, простой копипастой со стэковерфлоу, построят им КД на МС. Нет, они построят микролиты на ручной интеграции, сложность возрастет и все будет падать в разы чаще, количество велосипедов и говнокода будет расти в геометрической прогрессии.
Потери АСИК такие разрабы тоже не способны, по крайней мере сразу, пережить и начинается борьба бобра со злом, пока люди не придут к «как минимум раз» семантике, а там и ФП начинает махать радостно ручкой.
Нужны практики и опыт выстраивания таких систем (композиции их), которые работают и приносят удовольствие — это кластерные платформы типа к8с, окд а может и ранчер. Это использование ХА персистенц, что тоже очень не тривиально и далеко не все спецы это умеют. Это мониторинг и логинг этих решений, который тоже не прост. Отсюда далеко не всем крупным то компаниям понятен объем работ и разрыв знаний, который у них есть и тот, что нужен. Отсюда и появляются такие статьи.
А серверлесс — это дальнейшее развитие этих идей, где ФП и ДДД господствуют на сегодня.
Поток сознания какой-то и слишком много англицизмов. А серверлесс — те же яйца, только на минималках и иногда решающие мелкие инфраструктурные задачи из коробки. Где там ФП и ДДД — непонятно.

Некоторые люди, слово "монолит" — воспринимают как что-то "плохое", но это не совсем так, некорректно сравнивать в контексте что "лучше", это больше всего зависит от бизнеса и его масштабов.

И тут, вам придётся аккуратно последовательно отключать все ваши микросервисы и накатывать новые версии.

Кладётся рядом новая версия, на неё переключается дефолтный роут. Никаких отключений, никаких последовательно.

И новая версия начинает ругаться на плохие запросы

Only those users with full accounts are able to leave comments. Log in, please.