Pull to refresh

Comments 42

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

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

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


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


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

В статье не рассматривается вариант горизонтального масштабирования монолита.
Сервер приложений с Rest-style api вполне хорошо масштабируется горизонтально. Сервер БД можно либо шардить, либо делать мультимастер, либо просто добавлять readonly secondary.

Микросервисы решают не столько проблему масштабирования приложения, сколько масштабирования организации. Независимая кодовая база позволяет вносить одновременные изменения существенно большему количеству разработчиков с меньшим количеством усилий, чем монолит. Это позволяет добиваться улучшения святого Грааля современных организаций — time to market и разблокирует всякие приятные плюшки типа непрерывной поставки. С монолитом тоже можно, но очень дорого.

А чем их (организации) модульность не устраивает? Системы сборки (менеджеры пакетов — composer, npm, тот же maven) существуют давно. Платформы (типа Wordpress'а) с плагинами (высшая форма модульности на мой взгляд) — тоже имеют славную историю развития.


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


В Magento можно собрать приложение из модулей, разработчики которых даже не знакомы друг с другом. У каждого свой time to market и сопутствующие плюшки. Отдельные плагины можно update'ить без переразвёртывания всего приложения.


Так что я пока всё равно для себя оставляю главной причиной появления микросервисов именно необходимость (частичного) горизонтального масштабирования в приложении. Спасибо за ваше мнение.

>Платформы (типа Wordpress'а) с плагинами
Это вы щас JavaEE так обозвали? :)

Собственно говоря, да. Я вот никогда вообще не видел «монолитов», которые бы не были модульными. Все что я вижу примерно с 2004 года (до этого я просто фрилансил, т.е. было другое направление) — все так или иначе разбивается на модули, и делается командами в параллель. И таким образом, монолитом в чистом виде не является. А те кто не модульные — те быстро загибаются под своим весом и мрут как динозавры.
Это вы щас JavaEE так обозвали? :)

Я давно в JavaEE отсутствую, но там я видел самую лучшую изоляцию на то время :)) Да, JavaEE можно считать наиболее близкой к этой аналогии. Хотя и достаточно низкоуровневой. И без фронта.

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

Краткий ответ — изоляция «говнокода». Модульность перестаёт работать в тот момент, когда объём команды перерастает возможность контролировать ее код 1-2 людям, которые владеют всей полнотой информации об архитектуре и договоренностях по стандартам разработки. Вы перестаёте следить за всеми, появляются отклонения и код становится местами лапшой. В итоге «легаси проще переписать». Микросервисы сводят эту проблему к размеру сервиса. Можно наговнокодить отдельный сервис как угодно при помощи людей любой квалификации и это будет хорошо, пока он держит нагрузку и выполняет свои задачи. И тут как раз помогает раздельное масштабирование. При этом говнокод в одном из сервисов не затрагивает другие сервисы и команды. Profit.

Какая-то логика в ваших словах есть. Говнокод внутрипроцессный может завалить весь процесс. И модульность тут не поможет, а вот микросервисность — да.

Говнокод внутри процесса валит процесс.
Говнокод внутри микросервиса валит микросервис и все микросервисы, которые с ним работают.
Так или иначе, но приложение перестает работать.
Разве нет?

Не совсем. Сторонние сервисы могут отрабатывать отсутствие соединения с "падшим" сервисом и, допустим, откладывать обработку нужных данных в очередь. Прокинуть всё, когда сервис встанет.

Если вы про retry pattern, то звучит резонно, хотя монолит с балансировщиком могут делать тоже самое.
Если про очереди типа RabbitMQ, то монолит тоже может работать через них.
Просто возводя сетевые барьеры между кусками кода, вы не делаете его лучше.
Если вам нужен High availability, вы так же можете добавить его в монолит, это не эксклюзивная для микросервисов фича.

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


Подход микросервисов позволяет постепенно деградировать функциональность приложения. Работает на 100%, работает на 90%, ..., работает на 10%, "ваще не работает"...


P.S. Естественно подобную частичную деградацию функциональности приложение должно поддерживать, обічно на уровне архитектуры. Некоторые включают это в определение МСА. А то вроде бы по многим признаками микросервисов, но любая точка отказа ложит всё.

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

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


CatalogPage ShowCatalog(User user) {
  var isUserAuthorized;

  try {
    isUserAuthorized = Authorize(user);
  }
  catch {
    LogError("Authorization broken!");
    return GetGuestCatalog();
  }

   return isUserAuthorized ? GetUserCatalog(user) : GetGuestCatalog();
}

Здесь не видно, что именно делает ф-ия Authorize: вызывает микросервис или авторизирует с помощью подключенного модуля/библиотеки/пакета внутри процесса.
Но, на самом деле, какая разница? Приложение будет вести себя одинакового.

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

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


Очевидно, что если техдолгом не управлять, все развалится. Но это невероятно проще, чем в монолите.

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

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


Если нужно что-то более мобильное и эффективное типа LeSS или Spotify, то вам нужны микросервисы. Без них реализовать вменяемое покрытие автотестами гораздо сложнее. Потом вы ловите проблему атомарных релизов (одна фича, один релиз). Даже при наличии хорошего покрытия монолита вы попадаете в ситуацию очереди релизов и скорости релиза. Нормальной частью процесса является раскатка функционала и последующий мониторинг на наличие ошибок и проблем производительности под нагрузкой, т.е. некоторый период охлаждения. Если они проявились в промышленной среде, то релиз надо откатить. Сколько этот период должен длиться? Если час, то вы можете сделать 8 релизов за рабочий день максимум. Сколько релизов делает разработчик в день? У нас 1 релиз в 3 дня. Тут мы получаем 24 разработчика в команде максимум и это крайне оптимистично. По факту охлаждение надо делать больше и предел команды меньше.


Что происходит при превышении этого предела? Начинаются релизные поезда и merge кучи фич в одну ветку релизный кандидат. Из неё фиг выкинешь фичу с ошибками. Начинается циклический хотфикс-тест-хотфикс. Тут, по нашим расчетам, мы теряем до трети пропускной способности команды.


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

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

Но! одна платформа, одна архитектура ядра, и его основная версия на проде (и набор модулей-версий).
А потом надо обновить ядро или версию платформы/фреймворка. Технически все просто, максимум кратковременная остановка обслуживания. Если вы не Google, то это не критично.

Но вам надо обновить до новой версии и все плагины сразу! Тут собака и зарыта. Если у вас несколько команд, то за отдельный плагины отвечают разные команды, т.е. вам надо одновременно остановить развитие бизнес функционала во всех командах одновременно. А у одной из них дедлайн и тормозить нельзя. Ситуация «приплыли, все ждут». Особенно весело, когда вам надо обновиться, чтобы утечки памяти на уровне фреймворка устранить или похожее веселье. В итоге обновление превращается в совершенно адовый процесс, который стараются делать как можно реже, лучше никогда. Даже по SAFe у вас будет 4 окна в конце PI в год. Вот тут и помогает гетерогенность инструментов не в части тут пишем на Ruby, тут на Java, а в части разных версий одной и той же платформы. Процесс обновления доедет в асинхронном режиме по разным сервисам не блокируя бизнес. Это тоже стоит менеджерских усилий, но несоизмеримо меньших.

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

Естественно это работает для проектов достаточно крупного размера и мои замечания нерелевантны для команды в 5 человек, но в энтерпрайзе выбора пилить монолит давно уже просто нет.
Все это решается обратной совместимостью major vs minor upgrade, и в «монолите» с набором версий плагинов, это протестировать проще.

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

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

Во-вторых, на практике это невероятно дорого, т.к. нужно синхронизировать всех и провести общий регресс. А если команд 10? А если 100? Это никто не делает для плагинов/пакетов.

Возможно я экстремист и за последние 4-5 лет отвык от мира без непрерывной поставки и микросервисов, но я просто не могу представить, как сейчас можно писать новые проекты не в рамках MSA, если, конечно, хватает инженерных компетенций и ресурсов на первоначальные инвестиции. Т.е., ИМХО, монолит может быть оправдан только для хардкорного стартапа на самой ранней стадии или для проекта, который вообще не планируется масштабировать, т.к. уже через 3-4 месяца работы плюсы MSA начнут ощущаться.
Производство на микросервисах удобнее, когда появляются аутсорс-разработчики с точки зрения безопасности. Речь не только про среду выполнения, но и чувствительные данные, которые защищать надо не только от внешних факторов, но и от собственных сотрудников.

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

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

У монолитов тоже свои прелести. Одна опечатка и не работает вообще ничего. Или работает так, что лучше бы не работало.

Это если выкатывать на прод без какого-либо тестирования (или сразу править на проде).

И забить на практику интеграционных системных демо

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

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

Ну вот у меня проблема в одном сервисе, и он, как и всё остальное, обложен в какой-нибудь try-catch с логированием всех непойманных исключений. Как оно будет мешать работе других сервисов?
Зная его работу, он скорее кильнёт MySQL (подставьте любимое хранилище) при разрастании какого-нибудь микросервиса, чем один из десятков жрущих процессов самого микросервиса.

Хранилище будет на отдельных серверах, как обычно и с монолитами.

Например, через rollback транзакции в MySQL. В этой СУБД допустимы вложенные транзакции, но rollback внутренней транзакции откатывает все остальные. И try-catch тут не поможет. Нужно разделять контексты на уровне транзакций. Т.е., на базе монолита тоже можно писать микросервисно, но не выходя за границы процессов.


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


В общем, есть ещё у "монолита" запас перспективности, если его не слишком монолитным делать.

Ну да, от кривой архитектуры ничего не спасёт.
Вы не знаете что такое монолит, а лезете их сравнивать. Монолит маштабируется как вертикально так и горизонтально. Я всего 1 раз видел приложение которое не маштабировалось с кучей сессионных данных в памяти одного сервера, в остальных случаях делаешь копию и вот уже 2 огромных приложения делят нагрузку и так далее.
А теперь вспомним что такое микро сервисы, это самостоятельные куски монолита которые общаються между собой через какой-то протокол, тем самым при той же нагрузке, нужно больше памяти, процессорного времени и траффик между сервисами огромный. Из плюсов только то что работу можно разделить и не бояться что команда ответственная за калькуляцию сломает уровень работающий с хранением данных, но теперь нам нужен хороший архитектор который будет следить за общей картиной, чтоб разные куски не делали одно и тоже по разному, не таскали слишком много данных туда сюда и оптимировать места где пытаясь реюзать сервисы дошли до того что простая операция занимает много времени потому что бежит через 10 сервисов и тащит сотни мегов данных.
Вы не знаете что такое монолит, а лезете их сравнивать.

Ну и что? Вот вы, например, совершенно не умеете дискутировать. Но вам это не мешает.

Монолит (C#, MSSQL), но c:
1. SPA, чтоб каждый подраздел страницы был самодостаточным в разработке и модификации. Удобно.
2. Поддержкой микросервисов для задач с неопределенным уровнем нагрузки (Python через OpenAPI).
3. Доп. обвязкой: кеширование через Redis, LB и Reverse Proxy через Nginx
Пока проблем нет — шустро, просто, масштабируемо.

Важный момент: очень осторожно подходим к выносу фукнционала в микросервисы т.к., как было сказано выше, это повышенный maintenance.
Only those users with full accounts are able to leave comments. Log in, please.