Comments 105
Самая большая боль что если использовать эвентную модель , то обычно надо описывать единый микросерс на два хэдлера
например
{ PrepareBuyLot()
sendToBilling_PAY(userid, 50) }
А потом как бы еще хэндлить ответ
{ receiveMessageFromBilling()
MoreCodeForFinishBuyLoy() }
Кстати на картинке показано что в твитере более 500 микросервисов , я очень в этом сомневаюсь
Кстати на картинке показано что в твитере более 500 микросервисов , я очень в этом сомневаюсь
Я не сомневаюсь.
Работал 10 лет назад в провайдере SIP-телефонии. Вроде бы 1млн клиентов было, может поменьше. Микросервисы внутри плодились со страшной силой. Когда я пришел, то всю архитектуру из 10 сервисов знали наизусть все 30 сотрудников, включая, кажется, даже бухгалтера... Но пришло много творческих людей и через 7 лет, когда я увольнялся, количество компонентов приближалось к 200. Насколько мне известно, через пару лет перевалило за 300, а потом точное число мне уже не смогли назвать.
Сложность, истинную сложность системы невозможно уменьшить, съесть, скукожить и выбросить без того, чтобы снять покрытие каких-нибудь бизнес-процессов. Ее только можно сделать несколько более удобной для восприятия и хэндлинга разумным существом с конкретными особенностями восприятия. Нам легче воспринимать упорядоченную информацию, поэтому структурированные системы человеку постигать проще. Но структуризация - это добавочная истинная информация (как привнесённая в систему разумным существом), поэтому за неё тоже приходятся платить. Уменьшая и унифицируя компоненты, мы выдавливаем сложность изнутри наружу - в их связи. Декларируя соглашения по связям, мы пытаемся сделать их более управляемыми.
Здесь как в шумоподавителе Dolby - мы уменьшаем количество заметных человеком искажений за счёт увеличения количества незаметных. КПД этого процесса всегда < 1.
Полностью согласен. Вы практически сформулировали второй закон термодинамики применительно к информационным системам. В лучшем случае энтропия системы не растет, но при небрежном разбитии на микросервисы, неоптимальном дизайне и прочих других факторах сложность будет только увеличиваться.
Да, но примерно наоборот. Истинная сложность системы с введением даже неудачного разделения не вырастет - вырастет воспринимаемая человеком сложность. Представьте, что представитель некоего плоского мирка F не знает квадратных уравнений. Ему показывают график параболы, и он считает, что для описания набора точек на этой кривой нужно бесконечное количество информации. Затем приходит представитель выпуклого мира U, видит параболу, и говорит, что для ее описания на бесконечном интервале нужно всего три числа. Истинное кол-во информации для описания параболы будет равно этим трём числам. Воспринимаемое U - в данном случае = истинному. Воспринимаемое F - равно бесконечности.
В вашем определении сложность сугубо субьективна. У джуна она будет одна, у сеньора, корый посвящен в то, что рассматриваемый обьект парабола, другая. С таким определением сложно что либо сделать, кроме как сказать, что сложность есть, и более ничего.
Я понял вашу аналогию, позвольте дать другую. Есть программа для сжатия данных. Текст до сжатия занимает один мегабайт, после сжатия 100 килобайт. Учитывая, что современные алгоритмы пытаются учитывать не только универсальные свойства текста, но еще и его специфические особенности, эти 100 килобайт находятся очень близко к теоретическому пределу, к информации системы по Шеннону. В вашем примере, зная специфическую природу данных, эта информация свелась к 3 параметрам.
Так и сервис. Представим, что для конфигурации нашего сервиса можно задать 5 переменных, каждая из которых может находиться в 10 состояниях. Тогда, сервис имеет 10^5 состояний, каждое из которых уникально и может иметь свои побочные эффекты и особенности. Эти состояния(вернее его логарифм по степени 2) и есть энтропия системы, та мера хаоса, призванная оценить пространство возможных конфигураций. Возможных, так как сервис как правило будет находиться в одном из них в конкретный момент времени. Инженеру, как правило, эти состояния доступны и не скрыты. Заметим, что при таком определении сложность сугубо обьективна.
Проблема в другом. В том, что приходит задача поддержать некую фичу, которая нашей архитектурой не поддерживается. Вместо того, что бы менять архитектуру, вводится еще один параметр, где активируется фича - true или false. Таким образом, пространсво состояний умножается на два, а энтропия увеличивается на единицу. Такая система стала сложнее хотя бы потому, что разработчикам необходимо теперь учитывать при работе еще одну степень свободы, тестировать ее, что в масштабах большой системы невозможно. Поэтому, теряется контроль над системой, так как абстракций ее описывающих стало больше.
Прошу прощения за скомканный стиль, в коментариях тяжело подробно развертывать свою мысль.
Сложность, истинную сложность системы невозможно уменьшить, съесть, скукожить и выбросить без того, чтобы снять покрытие каких-нибудь бизнес-процессов.Но ее можно РАЗДЕЛИТЬ на части, так что для решения отдельных задач не нужно будет постигать всю систему целиком. Собственно такое разделение и есть основная цель микросервисов.
На мой взгляд, микросервисы - это промежуточная ступень к пониманию того, что на каждом уровне абстракции должно быть удобоваримое для мозга количество сущностей.
На текущий момент, проблема микросервисов в том, что люди не изолируют их в отдельные небольшие группы (подсистемы), создавая bonded context более высокого уровня, а сваливают в единую кучу, решив что два уровня абстракции достаточно (объекты внутри микросервисов и сами микросервисы). В итоге, мы выносим сложность решения с уровня кода, на уровень межсервисного общения и там её никак не решаем.
Следующий шаг, это организация микросервисов в группы. К примеру, с помощью неймспейсов в кубернетесе, стеков в aws или ресурсных групп в azure. Если их станет много, то строим следующий уровень (конвенциями в наименовании групп, виртуальными/реальными кластерами, отдельными аккаунтами облачных провайдеров).
В целом я полностью согласен и со статьёй, и с предлагаемым подходом к решению проблемы - кроме технических подробностей этого решения.
На мой взгляд, изолировать префиксами таблицы в БД и методы API - идея очень плохая. Равно как и собирать функционал в один микросервис по типам операций - все обработчики API в один, все фоновые задачи в другой… Это приведёт только к тому, что никакой изоляции между сервисами не будет - не теми, которые создаются сейчас в этом стиле, а теми настоящими микросервисами, на которые (возможно) придётся разделять эту систему в будущем.
Да, на начальном этапе разработки стоит использовать одно репо. Или очень небольшое количество репо - напр. по одному на каждый используемый в компании язык программирования, потому что у разных языков много своих особенностей в плане сборки и организации кода, и если их не смешивать в одном репо то жить становится проще.
Да, микросервисы в общем репо удобно разделять по каталогам, плюс отдельно общие библиотеки.
Да, на начальном этапе проще собирать и выкатывать все микросервисы одновременно, при любом изменении этого репо. Более того, можно даже сделать вообще один бинарник, в который встроить все эти сервисы, и деплоить, по сути, один сервис-монолит.
Но! При этом необходимо тем или иным способом обеспечить жёсткую изоляцию сервисов:
Одних каталогов мало, нужен ещё и автоматический контроль, что микросервис из одного каталога не использует код из каталогов других микросервисов. (Например, в Go это реализуется через internal-каталоги.)
Использовать общий сервис СУБД - да, но изолировать данные разных сервисов нужно не префиксами таблиц, а средствами самой СУБД. Т.е. у каждого микросервиса должен быть собственный аккаунт, дающий доступ только к его данным. (В MySQL каждому микросервису нужно создать собственный database, в PostgreSQL нужно создать разные схемы в рамках одного database и заблокировать доступ к схеме public, etc.)
API каждого сервиса должен реализовываться им самим и подниматься на собственном порту. (Т.е. в случае вышеупомянутого сервиса-монолита он при запуске будет раздавать API разных встроенных в него микросервисов на разных портах.)
В целом, такой подход приводит к тому, что в плане конфигурации всех этих микросервисов мы имеем практически то же самое, что имели бы при полностью раздельных микросервисах в собственных репо - толпу переменных окружения с именами вроде SERVICE1_MYSQL_PASS или SERVICE2_BIND_PORT. Но толпа переменных - это не страшно и сложности особо не добавляет.
А ключевое отличие (и сложность) моего подхода в том, что он не избавляет от необходимости с самого начала полноценно проектировать микросервисную архитектуру - иначе не получится разделить API и данные между микросервисами. Но без этого проектирования не получится (в будущем) разделить на настоящие микросервисы код написанный в предлагаемом в статье стиле! Так что либо мы на нём не экономим сразу, либо не нужно притворяться, что мы сможем сделать из этого проекта микросервисы в будущем.
Ну и в конце отвечу на заданный в статье вопрос: что мешает вместо микросервисов написать модульный монолит, для чего нужны границы процессов/API? В теории - ничего не мешает. Если нет каких-то серьёзных требований к масштабированию (а в 99.9% проектов их нет), то такой монолит вполне может решить все проблемы. Но на практике всё упирается в то, что если изоляцию этих модулей друг от друга не соблюдает на 100% бездушная машина, то люди её будут нарушать, обязательно, и скорее рано, чем поздно. А нарушенные границы приведут нас обратно к обычному спагетти-монолиту.
Равно как и собирать функционал в один микросервис по типам операций - все обработчики API в один, все фоновые задачи в другой…
Если убрать квантор ВСЕ, то достаточно неплохо получается.
Сама идея разделить фоновые процессы и АПИ хороша. Это же принципиально разные штуки, с разными sla, разными критериями быстродействия и разными мониторингами.
о люди её будут нарушать, обязательно, и скорее рано, чем поздно. А нарушенные границы приведут нас обратно к обычному спагетти-монолиту
Добавляем периодический рефакторинг с восстановлением границ и переделкой их на более хорошие. Я не уверен что это выйдет дороже поддержки микросервисов.
Рефакторинг с восстановлением границ часто может быть невыполним в разумные сроки. Ну, имхо. Иначе проблем бы вообще не было
Насчёт разделения фоновых процессов и API - да, это обычно хорошая идея. Но я писал именно про ВСЕ, и проблема в этом.
А вот насчёт рефакторинга Вы ошибаетесь - рефакторингом эта проблема не решается в принципе. Когда один сервис лезет во внутренности второго - это обычно не потому, что ему понадобилась удобная функция сортировки, которую можно и отрефакторить в отдельную библиотеку, а потому, что ему понадобилось что-то из данных, чего он не может получить через API - или вообще нет возможности, или слишком неудобно, или слишком неэффективно, или недостаточно атомарно… и вот это нужно решать на уровне архитектуры микросервисов. Причём решать это на уровне архитектуры когда фичу уже сделали с нарушением границ - обычно поздновато. А когда в таком стиле писали несколько месяцев - вообще без шансов. Потому что пока архитект будет думать и проектировать - разработчики наплодят новых связей.
Я никогда не понимал почему люди готовы делать нормальные модули в виде сервисов, но не в виде программных модулей? Это по сути одно и тоже.
АПИ это всегда накладные расходы на сеть. Микросервисы это проблема распределенных логов и распределенного дебага. При небольшой логической ошибке в проектировании появляется нерешаемая для большинства проблема распределенных транзакций. Надо пилить всякие circuit breaker, балансировки на разных уровнях и кучу производных rps считать и мониторить.
Нужно вам вот к этим данных ходить из разных мест? Такое бывает и это нормально. Ну вынесите ДАО для работы с ними в подходящий коммон модуль и ходите на здоровье.
Нужно вам надежно писать данные? Сделайте транзакцию в БД. Это почти бесплатная абсолютная гарантия.
Поняли что у вас спагетти образовалось? Соберитесь отделом разработки обсудите как это переделать хорошо и переделайте. Страшно только первый раз.
Я не про то что надо делать все одном монолите. Я про разумный баланс. Если у вас для отрисовки странички пользователю задействовано больше 2-3 ваших сервисов, то наверно вы пошли куда-то не туда. Стоит остановиться и подумать.
И в обратную сторону. Если вы поняли что из апишки пишите очередь заданий на обработать потом и в той же приложеньке читаете ее и обрабатываете наверно стоит подумать о разделении.
Ну, например, сервисы могут писать разные люди. В разных местах. И на разных языках программирования.
Сервисы надо масштабировать и деплоить - и это тоже может налагать условия на дизайн.
Если у вас для отрисовки странички пользователю задействовано больше 2-3 ваших сервисов, то наверно вы пошли куда-то не туда.
Так-то я с вами согласен по всем пунктам. Но если взять какой-нибудь распространенный сценарий типа, например, того же OAuth, то даже в документации можно насчитать 3+ разных сервиса, не считая баз данных, балансировщиков-прокси и кэшей на каждом.
Ну, например, сервисы могут писать разные люди. В разных местах. И на разных языках программирования.
Это худшее что можно придумать. Как это потом дебажить и поддерживать? Бизнесу глубоко все равно что у вас разные языки и команды. У него есть неработающая фича, или еще хуже внезапно сломавшаяся фича. Ее надо починить. Срочно.
У вас точно есть распределенный трейсинг, общее удобное хранилище логов, понимание как это все в комплексе работает и как это дебажить? Желательно чтобы этим всем владел один человек. Ему эту фичу чинить.
Сервисы надо масштабировать и деплоить - и это тоже может налагать условия на дизайн.
Вы никогда не столкнетесь с реальной необходимостью масштабировать разные вызовы АПИ по разному, чтобы это хоть как-то влияло на бюджет на железо. Тяжелую асинхронную обработку логично делать отдельно.
Так-то я с вами согласен по всем пунктам. Но если взять какой-нибудь распространенный сценарий типа, например, того же OAuth, то даже в документации можно насчитать 3+ разных сервиса, не считая баз данных, балансировщиков-прокси и кэшей на каждом.
Я именно про ваши аппликейшен сервера. Которые вы сами пишете и отвечатете за их работу.
БД, кеши, однозначно внешние сервисы за которые вы не под каким видом не отвечаете не считаем. Тут сложность тоже надо держать приемлемой, но эта задача перпендикулярна задаче держать количество ваших сервисов приемлемым.
С ростом сервиса меняется все.
Был проект на старом ASP.VB и древнючем IIS (кажется еще 4 версии, давно это было), начали переписывать под ASP.NET потихоньку. Внезапно директор получил нового большого клиента и много денег на развитие. Пришел крутой чел, сказал что все напишет на жабе, будет круто, быстро и с API. Начал переписывать, все затянулось. В итоге имеем уже три версии, которые друг без друга жить не могут. Это, фактически, монолит, но уже как минимум на трех языках. Рядом стоят SIP-сервера, телефонные сервера и биллинг. Часть на C (четвертый язык), часть вообще из опенсорса откуда-то скомпилена с конфигами то ли на lua, то ли хз на чем еще.. Еще огромный кусок логики в хранимках в базе Oracle (5 язык).
Деньги еще все не освоены, на Java набираются еще люди, у них начинаются терки за архитектуру, за версии и вообще за подход, старого мужика выгоняют и начинают писать заново. Ну вы знаете как это бывает. Еще одна версия.
Параллельно развиваются сисадмины. Раньше все делал один человек на 10 серверах - теперь нужно 10 человек для 200 серверов в 2 разных дата-центрах. А еще они научились мигрировать сервера на ESXi вживую и надо чтобы приложения поддерживали такую миграцию и не обрывали соединения (деплой влияет на логику и уровень приложений)..
Это просто вкратце и не полностью что случилось всего за год. Бизнес развивается стремительно и самое быстрое решение - не всегда самое правильное (но решение), вы и сами это знаете наверняка.
Всего за год три полных смены архитектуры и языка? Тут надо не кровати двигать на разработку и админов пинять. Тут большая проблема со всем руководством вашей разработки. И пока она не решена, все остальное не поможет.
А предложите вариант? Было 10к пользователей, внезапно выросло до 150к. Надо все очень быстро масштабировать. Деньги есть, времени нет. Конечно будут ошибки, но как же без них.
Кстати, все работало и все успели сделать к наплыву пользователей. Цена - вот такая вот. Пользователи пришли, принесли еще денег - наняли еще людей и уже не в такой спешке начали допиливать "по-нормальному".
Поняли что у вас спагетти образовалось? Соберитесь отделом разработки обсудите как это переделать хорошо и переделайте.
Это не работает, к сожалению. И именно этот факт окупает все эти лишние накладные расходы на API, деплой, распределённые логи и т.п.
Спагетти такая вещь, что если она в принципе может образоваться - она обязательно образуется. И никакое "переделать хорошо" не работает - ну потому что ведь и в первый же раз никто не собирался специально сделать плохо. Хорошо делали. А получилось спагетти. Собрались, обсудили, придумали как переделать хорошо… правда, по-простому никак, поэтому решили всё переписать. Ладно, уговорили бизнес, переписали. Допустим, даже успешно (что далеко не всегда бывает), и новая версия заменила старую. И знаете, что было дальше? А дальше через полгода снова образовалось спагетти. Ну потому что ничего же не изменилось - команда та же самая, писать все хотят хорошо, но сложность проекта всё время растёт, образованию спагетти ничего не мешает… Повторяя одни и те же действия в одних и тех же условиях - получаем один и тот же результат: спагетти.
Ну не совсем же так. Еще может быть подход таким: "пишем прототип" -> "рефакторим хорошо" -> "добавляем новые фичи или быстро правим когда меняются требования" -> "рефакторим хорошо".
По мере эксплуатации и добавления фич редко когда (никогда) получается следовать архитектуре из предыдущей итерации, копится технический долг и через какое-то время он закрывается. Если повезет - то целиком. Если не повезет - то частично и остаются легаси-артефакты вроде api/v1
Архитектура - это не что-то высеченное в камне. Меняются требования - архитектура тоже должна адаптироваться. Ожидать, что первой архитектуре удастся следовать вечно - довольно странно.
Тем не менее, есть принципиальная разница между рефакторингом кода и пересмотром архитектуры: код рефакторится "снизу", архитектура пересматривается "сверху". Именно по этой причине нужно и то, и другое, и они друг друга не заменяют.
Если спагетти получилось разобрать "снизу", рефакторингом кода - это было не то спагетти. А вот когда снизу ничего разобрать не получается, потому что на эту точку завязана куча других вещей, на те тоже завязана куча третьих вещей, и на этом общая картина уже начинает теряться, вместе с остатками понимания как всё это разобрать рефакторингом - вот тогда это оно.
И именно по этой причине описанный Вами подход - не работает. Пока проект относительно небольшой и молодой - кажется, что работает, но со временем и ростом проекта рефакторинг перестаёт справляться с поставленной перед ним задачей приведения кода в управляемое состояние.
(Извините, немного углублюсь в теорию вопроса.)
Задача архитектуры - провести границы, изолировать части проекта друг от друга, максимально ограничив связи между ними. Это необходимо для того, чтобы уменьшить когнитивную нагрузку - количество логических связей и переходов, необходимых нашему мозгу для осознания и понимания объекта, на который мы смотрим.
В этом смысле на уровне кода тоже есть своя архитектура. Условно, можно разделить "архитектуру" проекта на три уровня:
низкий: стиль (форматирование), идентификаторы (переменные, функции)
Типичный пример плохой архитектуры (отсутствия границ) на этом уровне - сделать все переменные глобальными.
средний: логическая структура (объекты/классы, пакеты, модули)
Типичный пример архитектуры этого уровня - "Чистая архитектура" дяди Боба, которая обеспечивает границы между внешним миром и бизнес-логикой, что создаёт возможность комфортно тестировать проект.
высокий: инфраструктура (микросервисы, API)
Рефакторинг затрагивает низкий и, частично, средний. Архитектура (в традиционном понимании) отвечает за высокий и, частично, средний. И как архитектор не может решить проблему с неудачными именами функций или глобальными переменными, так и рефакторинг не может решить проблему запутанных связей между высокоуровневыми модулями (и тут не важно, как эти модули называются - модули или микросервисы, - и как взаимодействуют - через API или вызовом методов).
В монолитах грань между средним и высоким уровнем… обычно сильно размыта и никем не контролируется. Если в микросервисной архитектуре сложно добавить новый микросервис или новые методы API в существующий сервис пройдя мимо внимания архитектора, то в монолите аналогичные изменения делаются незаметно даже для самих разработчиков, не говоря уже об архитекте. Границы, которые архитект определил в микросервисной архитектуре очень сложно нарушить в принципе, и абсолютно невозможно их нарушить нечаянно, даже не заметив этого. А в традиционном монолите - запросто.
Нарушая же границы и создавая новые связи - мы и занимаемся тем самым запутыванием кода проекта, после которого он превращается в комок спагетти, который уже невозможно развивать дальше, а можно только полностью переписать.
Поэтому крайне важно во время добавления новых фич чётко видеть установленные текущей архитектурой границы и не иметь (как минимум - простой) возможности их нарушать. А если их нарушить необходимо для реализации новой фичи - значит пора привлекать архитектора, чтобы он адаптировал архитектуру под изменившиеся требования и провёл другие границы. При этом очевидно, что никакой разработчик не будет бегать в доку по архитектуре каждый раз перед тем, как вызвать функцию - чтобы проверить, не нарушит ли этот вызов каких-нибудь границ в нашем монолите.
Сложные проекты, в которых нет архитектора, который бы провёл эти границы, или нет способа гарантировать соблюдение этих границ (как в большинстве монолитов) - обречены, и никакой рефакторинг их спасти не в состоянии. Извините за плохие новости, но это так, и на то есть вполне объективные вышеописанные причины.
У меня совершенно нет возражений на то что вы написали. Однако я уже не понимаю в чём вы не согласны со мной и товарищем выше.
Я не согласен с идеей (которую Вы с ним оба продвигали в этом треде), что все беды можно разгрести рефакторингом монолита, и тогда микросервисы вроде как не особо и нужны получаются.
Отнюдь. Я за монолит не топил никогда.
Моя идея была про рефакторинг архитектуры вообще. Сразу правильно и навсегда написать не получится. Можно правильно переделать существующий сервис, можно заложить в него возможности для планируемого расширения (попробовав предсказать будущие фичи).
Но в реальности все равно рано или поздно придут такие требования, что проще будет быстро добавить в код некрасивый хак, а потом уже правильно переписать через месяц или полгода.
Быстрый пример: есть две базы с разными данными, внезапно понадобилось сделать между ними join в одном запросе. Что-то придумывать сложное сейчас смысла нет, поскольку непонятно - нужно ли это будет через месяц. Я сделал одну таблицу через foreign table и связал их в запросе. Сделал пометку в TODO вернуться к этому через какое-то время. Потом можно будет оценить целесообразность переноса таблиц, выделения запроса в отдельный сервис или вообще выкинуть этот хак.
Хак добавить - это проще всегда. Правильно переписать потом - чаще всего не случается никогда. Частично потому, что хак работает, и нужно заниматься новыми фичами, а не пересмотром старых TODO. Частично потому, что нет ничего более постоянного, чем временное.
Пока такой хак один, и если его действительно пересмотреть и переделать нормально через месяц - в этом проблемы нет.
Но есть проблема в том, что хак вообще решились сделать. Потому что сделали один - сделают и ещё десять. А пересмотреть это уже не выйдет, потому что эти хаки связали ранее изолированные куски в одно целое, поэтому пересмотреть один хак не получится, нужно переделывать вообще всё, а это слишком долго и дорого, чтобы бизнес дал на это добро, тем более что никакого видимого (для бизнеса) эффекта от этой работы не будет.
Иными словами - это крайне скользкая дорожка, думать что такие хаки делать можно, и что ничем плохим это не кончится, потому что мы же "отрефакторим архитектуру" потом. Именно этот путь и приводит большинство монолитов в состояние комка, с которым невозможно ничего сделать.
Я на эту ситуацию смотрю иначе. Не в стиле "нужно ли это будет через месяц", а в стиле "если бизнесу уже понадобилась фича, которая не вписывается в текущую архитектуру, то это признак того, что архитектуру пора срочно пересматривать". И лучше пересмотреть её сразу, причём не под эту конкретную фичу, а под новое понимание сути бизнеса в целом, изменение (или изначальное недопонимание) которого и привело к тому, что такая фича не вписалась в текущую архитектуру. И здесь абсолютно неважно, отменит бизнес эту фичу через месяц или нет - важно что текущая архитектура явно не соответствует сути бизнеса, а данная фича просто вскрыла этот факт.
И вот в разрезе такого взгляда на ситуацию делать хак вместо пересмотра архитектуры - это просто вредительство, ничем не оправданное.
Не все так плохо. Я не про десятилетние наслоения кода. Я про нормальный живой проект. Его не надо переписывать полностью, его можно именно рефакторить по частям. Да, на это будет уходить определенный процент сил команды разработки. Но обычно он довольно терпимый.
Я бы оценил в 10-20 процентов сил команды разработки на поддержку кодовой базы с хорошем состоянии. Это постоянный процесс. Если забросить на годы, то потом плохо. Не надо забрасывать.
Экзоскелет. Просто в тренде. То, что в монолите когерентность состояния обеспечивалась ядром реляционной БД, надёжность которой выверена годами эксплуатации, сейчас не имеет значения. Вместо этого - самописные оркестраторы, способность которых фасилитировать бизнес-транзакции целиком на совести конкретного разработчика и/или девопса.
Вы справедливо указали на то, что такое решение возвращает нас к необходимости жестко соблюдать модульность. В статье речь идет о компромисе, позволяющем не скатываться в крайности, но и сохраняющем при этом их недостатки.
Насчет схем в PostgreSQL полностью согласен, не упомянул их только из за того, что не хотел привязываться к конкретному програмному решению. Не все базы данных такое поддерживают.
Что качается использованию разных портов для разных сервисов, это интересная идея. Я не думал об этом. Единственным припятствием к реализации такого решения вижу в отсутствии многопоточности. Что если используется однопоточный Python сервис, где нет возможности в подобном разделении? Хотя, это всего лишь догадка, необходимо поизучать эту тему.
Если честно, я вообще не верю в возможность использовать языки вроде питона в таком стиле - скриптовые языки не особо располагают к тому, чтобы обеспечивать жёсткую изоляцию в рамках одного приложения. Наоборот, обычно они предоставляют массу возможностей любую изоляцию обходить. Даже в Go писать изолированные модули/микросервисы в рамках монолита не было никаких шансов, пока не появилась поддержка internal-каталогов. Потому что без них Go обеспечивал жёсткую изоляцию на уровне только одного пакета, а писать целиком весь микросервис как один пакет… ну, такое.
Не все базы данных такое поддерживают.
Какие не поддерживают - те надо поднимать в отдельных инстансах, по одному на каждый микросервис. Сложности в деплое это добавит незначительно, но разные инстансы будут полностью изолированы друг от друга, доступ к ним будет с разными логинами/паролями, и микросервис не сможет добраться до чужих данных при всём желании.
В некоторых случаях несколько микросервисов могут работать с общей БД, но это во-первых исключение, и во-вторых в этом случае они не столько отдельные микросервисы, сколько разные инстансы одного сервиса. Да в этом случае немного необычно, что инстансы отличаются друг от друга (один раздаёт API, а другой выполняет фоновые задачи, к примеру), но с точки зрения архитектуры оба инстанса являются частью одного сервиса, у них одна граница ответственности, они оперируют одними данными - просто запускаются раздельно, не более того. А действительно разные сервисы в одну СУБД доступа не должны иметь в принципе - иначе любой изоляции конец.
PostgreSQL нужно создать разные схемы в рамках одного database
Не нужно. Постгря плохо переживает большое количество схем в одной бд. А вот большое количество самих бд - спокойно. Поэтому лучше сразу делать по отдельной бд для каждого сервиса с одной схемой в каждой
А есть какая-нибудь статья на эту тему или замеры?
https://stackoverflow.com/questions/14893964/how-many-schemas-can-be-created-in-postgres
https://postgrespro.ru/list/thread-id/2064050
Был еще один, более актуальный (около 1к схем, а не 10-20к) тред на StackOverflow, но не могу его найти. Там у человека pg_dump вообще крашился
Общая суть в том, что при дампе такой большой бд pg_dump должен развесить кучу локов и все проверить, что очень сильно замедляет процесс (вплоть до невозможности делать это ежедневно) или вообще приводит к его падению
Возможно, в более новых версиях это пофиксили, не проверял (у нас не настолько много сервисов)
Использование отдельных бд требует отдельного коннекшена к каждой, что тоже может стать проблемой. По сути выбор между проблемами с бэкапами или проблемами с коннекшенами
Но в случае отдельных бд мы полностью исключаем использование чужих данных из других схем
Проблема не выглядит реальной для нашего use case. Во-первых, обычно в проектах нет такого (тысячи) количества stateful микросервисов использующих именно постгрес. Во-вторых, тупо из соображений производительности никто не направит даже сотню таких микросервисов в общий инстанс постгреса. Обычно речь идёт о порядке десятка(ов) микросервисов на один постгрес.
Тогда тем более лучше разделять по бд их. Потому что на таком объеме вы не перегрузите его количеством коннекшенов, но при этом обеспечите 100% изоляцию разных сервисов, просто не давая возможности на уровне бд влезть в соседнюю схему
Для того, чтобы запретить влезать в соседнюю схему, разделять БД совершенно не требуется.
Не требуется, но это бесплатная гарантия на уровне бд. Так еще и ускоряет и упрощает дампы потом. Так-то много где и что можно отдельно гарантировать, на уровне CI код проверять и прочее. Но зачем?
Меня вот все минусуют, но я вижу в ответ только спорные высказывания типа "плюсы - не плюсы", а не проблемы и конструктив. И тихие нажатия на кнопочку "-rep". Собственно, говорит многое о уровне несогласных)
Смотрите, для того чтобы создать отдельную БД для сервиса, получив "бесплатную гарантию" 100% разделения сервисов, нужно сделать что?
- Завести отдельного пользователя для этого сервиса;
- Создать БД;
- Дать права на БД из пункта 2 пользователю из пункта 1
Теперь смотрим как то же самое делается для схемы. Нужно:
- Завести отдельного пользователя для этого сервиса;
- Создать схему;
- Дать права на схему из пункта 2 пользователю из пункта 1
В чём разница-то, ёпрст? Почему у вас первое — бесплатно, а второе требует проверки кода на уровне CI?
А что по версионности? Кто как организует хранение старых версий?
Если Вы про API (хотя тут неясно о каком "хранении" речь), то самый лучший совет - не относится к версионированию с лёгкостью.
Поддержка старых версий - боль. Поэтому нужно очень стараться проектировать так, чтобы версия была одна. Да, это не всегда возможно (но чаще - просто нехватает квалификации, либо потому, что нормального архитекта на проекте нет, либо потому, что он делегировал проектирование API разработчикам). Но очень многое зависит от того, какую стратегию мы выбрали: либо стараться изначально лучше продумывать API и развивать его насколько это возможно без потери совместимости, либо при любых проблемах сразу выпускать новую несовместимую версию API и полагаться на версионирование как на способ решить все проблемы.
Версионирование API как способ решения всех проблем чем-то напоминает идею плодить сотни микросервисов как способ решения всех проблем - какие-то проблемы это решает, но и новых проблем добавляет немало.
Из этих соображений я не люблю использовать версионирование первой версии API - вроде /api/v1/ для REST или pkg.v1 для gRPC. Это не мешает в будущем начать использовать v2, но сам факт того, что это будет смотреться не очень элегантно (/api/register и /api/v2/register) чисто психологически стимулирует оттягивать появление v2 как можно дольше.
В целом, проблема тут не столько в номере версии - в конце концов никто не мешает рядом с /api/register сделать /api/register_oauth или тупо /api/register2. Проблема в том, что новые методы API нельзя добавлять с лёгкостью, и не важно, какой у них префикс версии. Но новая версия как бы "подталкивает" к тому, что можно сделать улучшенную копию всего старого API, и к тому, что если с первой попытки это не выйдет, то можно ещё новых версий сделать будет - что в результате приводит к появлению намного большего количества новых методов API, чем необходимо. В т.ч. и потому, что кажущаяся лёгкость переделки API позволяет меньше сил уделять качественному проектированию, что увеличивает количество и ошибок и новых версий.
Не согласен с тем, что надо оттягивать появление новых версий итд. Это попросту не возможно в долгоживущем апи.
Посмотрите апи Телеграм, там версионность сделана через так называемые слои - layers. Текущий слой уже переваливает за 100:
https://core.telegram.org/api/invoking#layers
https://core.telegram.org/api/layers
То есть когда они добавляют поле в метод или меняют объект, добавляют новый метод и поднимают версию. Старая версия при этом поддерживается.
На клиенте же в switch по crc32 коду возвращаемого объекта смотрят что это за объект пришел (метод в общем случае может вернуть разные обьекты) и десереализуют данные в объект.
Не уверен, что у ребят из Телеграм не достаточно опыта, как вы выразились ;)
Было очень интересно с точки зрения изучения кода глянуть на их реализацию, как это все организовано.
Уверен на 95% что там монолит. Так как бекенд ВК был монолит, который компилился в vk.exe на 4гб
Из моего опыта, для взаимодействия всех сервисов продукта важно иметь метаданные в некой БД:
схему данных, которая включает в себя:
1.1. Classes - словарь классов
1.2. Properties - словарь свойств
1.3. Enumerations - используются в №2
1.4. ClassProperties - свойства классов (№№1+2)
1.5. ClassRelations - иерархия и связи между классами (inheritance, subclasses and superclasses)репозитарий сервисов
схемы запросов/ответов для каждого сервиса (№2), которые опираются на №№ 1.1, 1.3, 1.4
возможность генерить sample payload, на основании схем (№3)
mocked API endpoints - тестовые сервисы, которые на основании №3 и №4 позволяют протестировать
Как бонус:описание процессов через BPMN, как сложная логика взаимодействия сервисов
оркестратор сервисов и процессов, BPM engine, если возможно (Camunda)
Для упрощения и масштабирования, метаданные желательны, но можно и без них.
И, насчет управления метаданными:
желательно веб-приложение для работы с этими данными,
желательно легко расширять метаданные, чтоб можно было легко навешивать автоматизацию или добавлять описание
желателен легкий доступ к метаданным из внешних продуктов, чтоб легко генерить документацию и упрощать интеграцию
Из чего следует, что метаданные лучше хранить в стандартной DBMS, типа реляционных Postgres, MSSQL, MySQL, etc.
А кто это будет поддерживать?
Как будет гарантированно 100% соответствие тому что в проде?
Чем вы будете бить своих разработчиков чтобы они не забивали на поддержку этого?
Я неясно описал: метаданные выше, это primary source of truth, автоматизирующий часть задач.
На основании этого описания формируется swagger сервисов, для этих mock формируется код с функционалом микросервисов.
Т.е., отвечая на ваш вопрос - не нужно синхронизировать, нужно дополнять кодом и оборачивать devops CI/CD для deploy на среды (test, dev, dr, etc.).
Не. Правда только то что на проде. И в любой момент прод будет обгонять любое описание и любую документацию. Разработчики так код пишут. Бизнес так деньги зарабатывает. Консенсус.
Разработчик сам по себе без проблем сделает условный swagger. На той технологии которая лучше всего стыкуется с его языком и фреймворком. Это несложно и правда удобно. Возможно разработчик даже доку напишет. Текстом с примерами кода. Это чуть сложнее, но тоже полезно и замотивировать на это несложно.
Для остального нужна какая-то сильная мотивация чтобы ваши разработчики вот это вот все поддерживали и не забивали. Я предполагаю что для этого их надо ежедневно бить. Других вариантов я вообще не вижу. Ваша схема очень трудозатратна, а однозначной пользы разработка в ней точно не увидит.
Для примера прикиньте сколько сил в вашей схеме займет небольшой рефакторинг вида: Из кучи бизнес логики выделили несколько новых ДАОшек/сервисов и обобщенным кодом и запихнули их в отдельный модуль. По пути переименовав полсотни классов и изменив пару сотен связей внутри.
Сколько это делать у вас? Как валидировать что все соответствует продакшен коду? Обычный код валидируется тестами. Интеграционные тесты идеально проверяют такой сценарий рефакторинга.
Я предполагаю что для этого их надо ежедневно бить. Других вариантов я вообще не вижу.
А так и есть.
Один раз разработчик зашел на продакшен и залил конфиг с совсем небольшим изменением. Только забыл что у него Windows, а на сервере Linux, и переносы строк другие. Через какое-то время сервис подхватил конфиг и все упало. Искали долго (визуально конфиг тот же самый). Сильно поругали, но простили.
В следующий раз другой разработчик залез в базу на продакшене и что-то поправил, залочил компьютер и ушел домой. Соединение с базой забыл закрыть. База нашла открытую транзакцию, немного подождала и ушла в дедлок. Все упало. Разработчика выпороли, но простили.
В итоге доступ на продакшен закрыли всем разработчикам без вариантов. Для обновления чего-то они пишут детальную инструкцию по всем серверам и отдают ее в Operations. Те уже сами раскатывают все на отдельном энвароменте, там оно тестируется и те же люди катят все в продакшен по той же инструкции. Если что-то не раскатывается - идет обратно и всех ругают.
Один раз разработчик зашел на продакшен и залил конфиг с совсем небольшим изменением. Только забыл что у него Windows, а на сервере Linux, и переносы строк другие. Через какое-то время сервис подхватил конфиг и все упало. Искали долго (визуально конфиг тот же самый). Сильно поругали, но простили.
Написать код так чтобы он работал с любыми переносами строк так и не догадались? Сделать мониторинг вот такого падения с откатом конфига/версии приложения по одной кнопке тоже не догадались?
Ругать просто. Но это никак не помогает. И сильно вредит.
В следующий раз другой разработчик залез в базу на продакшене и что-то поправил, залочил компьютер и ушел домой. Соединение с базой забыл закрыть. База нашла открытую транзакцию, немного подождала и ушла в дедлок. Все упало. Разработчика выпороли, но простили.
Странная у вас БД которая падает от одного дополнительного коннекта или транзакции. У всех приличных БД есть куча разные ручек с разными настройками, которые позволяют автоматом все неприличное отключать.
Вероятно у вас после этого минус хороший разработчик будет. А то и несколько, ибо слухи.
В итоге доступ на продакшен закрыли всем разработчикам без вариантов.
А когда продакшен пришел в непонятное состояние и деньги бизнеса горят ярким факелом кто это чинит? Допустим простой откат версии не помог.
Уважаемый сэр, я согласен что должно быть хорошо, а плохо не должно быть, но так не всегда получается.
Написать код так чтобы он работал с любыми переносами строк так и не догадались?
Kamalio SIP server (он же OpenSer) - опенсорсная тулзовина. Напишите им сами об этом.
Странная у вас БД которая падает от одного дополнительного коннекта или транзакции.
Мне кажется что почти в любой базе можно запросто устроить дедлок просто забыв сделать коммит. А если у вас в одной IDE две вкладки - для продакшена и для локального сервера - вполне можно и не в том его сделать.
А когда продакшен пришел в непонятное состояние и деньги бизнеса горят ярким факелом кто это чинит? Допустим простой откат версии не помог.
Было всего один раз за следующие 6 лет когда легло просто ВСЕ. 6 часов чинили особо ответственные люди, директор бегал вокруг и рвал все волосы во всех местах себе и окружающим. Были сделаны сильные выводы, показательно уволено много людей, включая VP по разработке. Те кто остались - запомнили. После этого архитектура стала такой что просто ВСЕ упасть уже не могло сразу.
Уважаемый сэр, я согласен что должно быть хорошо, а плохо не должно быть, но так не всегда получается.
Мне кажется что вы даже не стремитесь к тому чтобы получалось.
Kamalio SIP server (он же OpenSer) - опенсорсная тулзовина. Напишите им сами об этом.
Не использовать тузлу в которой есть такие примитивные ошибки.
Сделать PR в мастер.
Форкнуть и дописать.
На самый крайний случай обнести прод именно этой тулзы дополнительным забором. Если против остальных методов есть очень убедительные аргументы.
Выбирайте.
Мне кажется что почти в любой базе можно запросто устроить дедлок просто забыв сделать коммит.
Нет. По крайней мере случайно точно нет, при адекватных настройках этой базы. Специальное вредительство рассматривать не будем.
Были сделаны сильные выводы, показательно уволено много людей, включая VP по разработке.
У меня один вопрос остался. Как эта фирма называется? Чтобы не вляпаться случайно.
Есть тут на хабре один товарищ, nmivan, знаменитый своими рассказами про героя Сергея, который дАртаньян и всем героически указывает как надо делать правильно, а почему-то все глупые и его не слушают.
Так-то все умные и указывать на чужие ошибки через 20 лет довольно просто.
Конешн, чего там - взять Kamailio или Asterisk, найти там все баги и пофиксить. На один вечер работы.
Были сделаны сильные выводы, показательно уволено много людей, включая VP по разработке. Те кто остались - запомнили. После этого архитектура стала такой что просто ВСЕ упасть уже не могло сразу.
Во-первых, сомневаюсь, что такую архитектуру можно сделать.
Во-вторых, раз за шесть лет - увольнение. Серьёзно? Считали процент доступности то? Или в 100% метите?
В-третьих, часть разработки уволили, часть адекватных сами ушли, оставшиеся будут бояться что то делать. Профит
Во-первых, сомневаюсь, что такую архитектуру можно сделать.
Ну, общие точки есть всегда, конечно. Разнесли пользователей по 6+ разным окружениям с отдельной инфраструктурой и в 3 дата-центрах, сначала Active-Passive, а потом частично Active-Active схема. Больше 4к серверов только на продакшене, в 2-3 раза больше в тестовых окружениях. На время больших обновлений пользователи переносятся в другое окружение, переключаются все девайсы и звонки..
Про реальную доступность я лично не знаю, но "пять девяток" было заявлено, а уж как это считалось - не в курсе. Вроде бы проходили какой-то аудит перед IPO, но я этим не очень интересовался тогда.
Факапы есть всегда и у всех. Кто-то делает выводы сразу, а кто-то уже после второго раза. Я видел много разных историй, но рассказывать про многие будет неэтично.
Были сделаны сильные выводы
А что за сильные выводы, кстати?
Правда только то что на проде.
Это кохоз, а не правда.
Должно быть separation of duties, когда разрабочики не имеют доступ на прод, а прод обновляется через автоматизированные CI/CD.
Офтоп:
Минус за мой коммент выше - гигантский демотиватор.
Какой смысл делиться мнением, если хамовитый оппонент тупо заминусует?
Я не пишу статьи и когда Хабр меня уведомляет, что я не могу комментировать т.к. моя карма в плинтусе, причем я никого не оскорблял и не обижал словом ... хочется вежливо послать и оставаться при своем мнении.
Ci/CD и доступ разработки на прод это перпендикулярные вещи. Они отлично живут одновременно. Доступ нужен для тушения пожаров и дебага неповторимых нигде, кроме прода, проблем.
«Правда только то что на проде» это суровая правда жизни. Нельзя считать правдой то что не работает и может быть никогда не заработает. Это путь в тупик. У вас будет «официальный источник правды» и народ который шепотом будет говорить новичкам где на самом деле посмотреть правду.
Если деплой на прод делается автоматическими средствами, то не очень много смысла что-то "шаманить" руками на проде, потому что следующий деплой все затрет обратно.
Тогда "правда" и переезжает в скрипты деплоя. Ну или в те части, которые ещё не автоматизированы.
Ваши советы от тяжелых условий, но оторваны от стандартов разработки.
Зарубежные аудиторы (SOC2) запретят доступ к вашим продуктам т.к. у вас любой разработчик может зайти на прод и не только подшаманить код, но и:
- скопировать данные клиентов (для траблшутинга, конечно)
- вставить зловредный код, пока не будет перезатерт след. деплоем
Обе истории не выдуманные, а из моей практики.
Зарубежные аудиторы (SOC2) запретят доступ к вашим продуктам
SOC аудит требует аудита каждого доступа на прод и вроде как логов всего что там делалось. Джамп хосты с логированием всей ssh сессии с заведение тикетов на каждый логин на прод сервер полностью удовлетворяют этим критериям.
Аудиторы это нормальные люди. Они не выдумывают неисполнимых требований. Они понимают что работать как-то надо. Все требования в основном про прозрачность и бюрократию.
Обе истории не выдуманные, а из моей практики.
Уголовные дела покажете? Второй случай это чистая уголовщина.
С учетом текущих зарплат и рынка можно считать вектор атаки "разработчик сознательно совершает уголовное преступление" несущесвенным. И защищаться путем автоматического сбора улик с заведением уголовного дела. Сотрудник конечно же должен быть в курсе что собирается. Это защитит нас в достаточной степени.
SOC аудит требует аудита каждого доступа на прод и вроде как логов всего что там делалось.
Написанное вами пересказывает мои слова.
Благодарю за минус. :)
Консультируя в банковском секторе, сейчас прохожу очередной SOC2 type2 в стартапе и прошел для своей среды в дата центре и не соглашусь.
Аудиторы это нормальные люди.
Странное панибратство.
SOC2 - не нормальные люди, а процессы и и правила соблюдения этих процессов.
Как только регуляторы обнаруживают, что аудиторы нормальные люди и можно срезать углы в вопросах безопасности, требования к аудиту сразу изменят.
Именно так случилось с SAS70, который был ранее, в 200х.
Уголовные дела покажете? Второй случай это чистая уголовщина.
Вы часто видели случаи, когда компания выметает мусор и роняет свою репутацию?
Зачем эти пафосные выражения?
В нашем случае: сотрудника ловят на сборе, блокируют доступ, проводят расследование и увольнятют по-тихому.
Написанное вами пересказывает мои слова.Благодарю за минус. :)
Нет и нет. Между запретом и логами с аудитом есть огромная пропасть.
Я не минусовал
SOC2 - не нормальные люди, а процессы и и правила соблюдения этих процессов
Я тоже проходил аудиты и общался с аудиторами. Нормальные люди это в смысле их цель не запретить вам работать или не завалить вас на аудите. А обеспечить нужный уровень безопасности. Это достигается без всяких экстремальных методов которые вы предложили вот тут https://habr.com/ru/post/668300/comments/#comment_24387092
Вы часто видели случаи, когда компания выметает мусор и роняет свою репутацию?
Это как раз повышение репутации. Готовность наказывать по закону своих сотрудников, которые сознательно нарушили уголовный кодекс, поднимает доверие к компании и ее сотрудникам.
Доступ разработки на прод - это способ создать проблемы, а не решить их. Да, в виде исключения, кто-то один, самый главный и ответственный, этот доступ может иметь. Техлид/архитект/техдир - такого уровня главный, в зависимости от размера компании. Но точно не разработчики. И, по возможности, даже этот доступ должен быть read-only - типа посмотреть в БД прода чтобы понять что в ней не так, но не фиксить её ручками - фиксить надо выкатом штатной миграции через CI/CD.
Для дебага именно "доступ" - не нужен. Для дебага есть куча инструментов, от логов и метрик до встроенного профайлера. Это - доступ уровня read-only, от него проблем нет. Да, это может требовать выката отладочных версий штатным CI/CD - но это хорошо, а не плохо. Уж всяко это лучше, чем ручками на проде менять код (если это скриптовый язык) или напрямую БД.
Что до правды - Вы правы. Если на проде одно API, а по доке должно быть другое - правда на проде. Но решать эту проблему (а это проблема!) нужно с другой стороны: поставить процессы так, чтобы на проде физически не могло оказаться что-то, что не описано в доке на API. Это довольно просто: любое изменение API сначала делается в доке, а уже потом в коде (в идеале - путём кодогенерации из доки).
Это довольно просто: любое изменение API сначала делается в доке, а уже потом в коде
Ага. Вот сделал разработчик изменение API в доке, и внезапно заболел. Или уволился. А задача, которую он делал, оказалась не такой срочной и упала в бэклог. Что дальше по вашим процессам происходить будет?
(в идеале — путём кодогенерации из доки)
Фундаментальная проблема кодогенерации бэкенда — в том, что сгенерировать можно только "заглушку", но не реализацию. А разницы между ошибками "конечная точка не найдена" и "конечная точка не реализована" немного — в обоих случаях API не работает.
сделал разработчик изменение API в доке, и внезапно заболел. Или уволился
сделал - в смысле закоммитил? То есть закоммитил только часть задачи? В рабочую ветку? И код-ревью допустило этот пулл-реквест? И тесты не нашли что дока не соответствует апи? Ну тогда все плохо будет, конечно.
Если дока и реализация в рамках одного реквеста делаются, то что значит "любое изменение API сначала делается в доке, а уже потом в коде"?
Ветка началась с предложения держать метаданные в БД.
Возможно, конечно, что имелась в виду файловая БД лежащая в гите, но говоря о БД обычно всё же имеют в виду серверные варианты. Где нет никаких веток и пул-реквестов.
Опять же, даже в случае файловой БД возможности ветвления и пул-реквестов резко ограничены форматом.
Разница громадная: API прода либо соответствует доке, либо нет. А то, что часть методов может не работать (возвращать 501 Not Implemented в случае HTTP API) или не работать корректно (напр. возвращать 500 Internal Server Error) - это штатная ситуация, и клиенты должны быть к этому готовы в любом случае. Но клиенты не должны получать ошибки вроде 404 Not Found или 400 Bad Request (говорящие о баге в коде клиента!) если они отправляют запросы соответствующие доке на API.
Вы точно код для прода пишите и мониторите?
Пятисотки это первый сигнал что у вас что-то сломано. Код который может отдавать пятисотки не должен доежать до прода никогда. А если доехал, то чиниться asap.
При этом фон 4хх есть всегда и везде. Клиенты ошибаются и это их право. Их так строго мониторить нет смысла. Возможно есть смысл мониторить необычные всплески или необычное распределение. Тут уже зависит от специфики проекта.
Документация написанная и выложенная после релиза прода дает гарантию что все методы из нее работают. Понятно что сломаться может все. Но это авария которая будет максимально быстро чиниться.
Вы не уловили суть. Вы описываете отношение с точки зрения бэка, а я с точки зрения клиента.
Для бэка 500 на проде возникать не должен, а если возник то это бывает крайне редко, сопровождается алертами и быстрыми хотфиксами. Для клиента 500 - это то, что он должен быть готов в любой момент получить и обработать.
Для бэка 400 это ситуация штатная, мало ли что клиенты прислали. Для клиента 400 - это признак бага в коде клиента, и в проде такое случаться в принципе не должно (аналогично 500 в проде на бэке).
Документация на API описывает представление архитекта о том, как оно должно работать, и даёт возможность параллельно разрабатывать как сервер, так и клиент. Именно поэтому при изменении документации имеет смысл сразу генерировать заглушки на сервере - как минимум это избавит корректно реализованного клиента (помните - его пишут параллельно с сервером, и могут реализовать раньше сервера) от получения 400 (приводящей к поиску несуществующего бага в коде клиента).
Документация на API описывает представление архитекта о том, как оно должно работать, и даёт возможность параллельно разрабатывать как сервер, так и клиент
Документация описывающая фантазии кого угодно бесполезна полностью. Для всех. Документация должна описывать то что есть и работает. Неполнота документации гораздо лучше фантазий в документации.
Параллельное написание клиента и сервера бывает. Договориться кто и как мокает серверные вызовы обычно несложно. С учетом максимальной гибкости и быстрого изменения этих моков. Разработка идет, всегда что-то меняется. Не вижу зачем зачем тут формализованный процесс. Точнее так: Если вам нужен формализованный процесс в этом месте, значит параллельная разработка вам не подходит. Надо подождать пока бек напишут и докатят до прода.
Документация должна описывать то что есть и работает.
Есть подход, когда документация пишется после кода. Тогда так и получается. Один из недостатков - документация всегда отстаёт от кода. Другой - часто она очень сильно отстаёт от кода, настолько, что можно сказать что она отсутствует в принципе. Третий - она может описывать фантазии, а не то, как реально работает код. Ну т.е. при этом подходе она всегда врёт.
Есть другой подход, когда документация пишется до кода. Ну, знаете, вот эти вот олдскульные ТЗ. В этом случае реализация может отставать от документации, но она всегда ей соответствует - потому что пишется глядя в доку и принимается на ревью тоже глядя в доку. В отличие от предыдущего подхода, если документация и не соответствует текущей реализации, то это временно - что и даёт возможность спокойно писать клиенты параллельно с бэком.
Ну, знаете, вот эти вот олдскульные ТЗ.
Мы живем в мире agile, user story, еженедельных релизов и фича флагов с экспериментами.
Стабильное ТЗ на продолжительной срок это уже много лет как что-то эфемерное. Бизнес уже сделал свой выбор что ему важнее.
Не вижу смысла сопротивляться в этом месте. Как подстроиться под такие требования бизнеса уже придумано. Выходит не так плохо на самом деле. Eventually нормальный код писать можно с такими вводными.
ТЗ аджайлу не помеха. Просто их надо уметь писать. И не писать ТЗ на весь проект, а писать его только на тот функционал, который запланировано делать в ближайшие недели.
И ТЗ при таком подходе никак не замедляет разработку - просто то, над чем бы в любом случае пришлось думать в процессе написания кода, обдумывается заранее и описывается в документе. В среднем, такой подход разработку ускоряет, а не замедляет, как было во времена водопада.
Я люблю работать с людьми для которых ТЗ на двухнедельную фичу занимает абзац текста. Джуны или новички в команде это исключение. С ними работаем индивидуально.
Более крупные фичи декомпозируем до тех же двух недель. Сколько работы по декомпозиции сделает сам исполнитель, сколько придется сделать за него зависит от и бывает по разному. В идеале он все сделает сам и надо только проверить что там не вышло какой-то дичи. Проверять можно на дизайн ревью. Когда человек выходит и рассказывает своей команде что и как он будет делать. А команда набрасывает, ищет логические ошибки и технические проблемы.
Еще более крупные фичи тоже декомпозируем вместе с людьми из бизнеса. И отдаем в разработку когда там уже понятно разработчику что надо получить в конечном итоге. Перевод с языка бизнеса на язык разработки делается тут же.
Целевое состояние понятно. Подробные ТЗ написанные сверху в него никак не укладываются. Они убивают все развитие разработчиков и их активность. Такие разработчики не являются целевым состояние команды.
Размер ТЗ на 2 недели определяется исключительно тем, сколько всего необходимо продумать для реализации этого функционала. Если это что-то типовое для этого проекта или вообще тупой CRUD - да, это может быть абзац текста. Если что-то достаточно сложное - ТЗ может быть детализировано вплоть до описания конкретного алгоритма, и займёт это далеко не один абзац. Тут важно то, что сколько бы не заняло ТЗ - оно не содержит воды и лишних подробностей, только то, что в любом случае пришлось бы продумывать при написании кода.
И это все пишет тот человек который код писать будет. Потом только валидация что он дичь какую-то не придумал.
Если людям не выдавать сложные задачи где надо подумать, то вы растеряете всех инициативных людей и вероятно даже останетесь без сеньоров. Ну не любят они такое отношение к себе и такие задачи где все творчество сделано за них.
Микроменеджмент вот тут где-то рядом стоит. Его обычно считают абсолютным злом которого надо избегать всеми силами.
А кто сказал что ТЗ за этого сениора пишет кто-то другой? Написание ТЗ перед реализацией - это просто поставленный процесс. (Кстати, большая часть моих комментов под этой статьёй - как раз про постановку правильных процессов.)
Если сениоры тянут написание ТЗ для собственных задач - пусть сами и пишут. ТЗ всё-равно потом проходит ревью/аппрув у бизнеса или архитекта.
Как клиент отработает 500 если она всегда возвращается?
Штатно - повтором запроса с экспоненциальной задержкой и/или уведомлением юзера. Я к тому, что клиент должен в любом случае иметь поддержку этой ситуации.
На практике, если бэк ещё не реализован, а для продолжения работы по реализации клиента ему нужен осмысленный ответ от этого API, то клиенту приходится использовать мок. Это не очень хорошо, потому что тратит время разработчиков клиента сначала на добавление этих моков, а потом на удаление, плюс создаёт вероятность что мок будет возвращать некорректные данные из-за чего их обработка в клиенте будет написана тоже некорректно - но тут уже вопрос к тому, как PM организовал последовательность задач для бэка и для фронта, и нельзя ли было организовать её как-то иначе, чтобы не пришлось тратить время на лишние моки.
Да, в виде исключения, кто-то один, самый главный и ответственный, этот доступ может иметь. Техлид/архитект/техдир - такого уровня главный, в зависимости от размера компании.
Вы только то поставили всю компанию в зависимость от одного человека. При этом того кто вероятно не в курсе конкретики того что в проде крутится. И значит не может лично разобраться почему та или иная дичь внезапно начала происходить.
Вера в волшебника на голубом вертолете который прилетит и все починит это очень наивно. И не работает на практике.
Чинит тот же коллектив который код пишет. Только он в курсе что там на самом деле творится. Большое руководство должно заботиться о бас факторе и прозрачности того что делается в проде. В идеале еще иногда интересоваться мнением команды разработки о качестве кода и выслушивать предложения что там улучшить можно. И большому руководству стоит не забывать выдавать премии за повышение стабильности, прозрачности, качества мониторинга, качества кода и выбивать у бизнеса время разработчиков на эти действия. Это все. Лазить руками в прод руководству точно не нужно.
Что до правды - Вы правы. Если на проде одно API, а по доке должно быть другое - правда на проде. Но решать эту проблему (а это проблема!) нужно с другой стороны: поставить процессы так, чтобы на проде физически не могло оказаться что-то, что не описано в доке на API. Это довольно просто: любое изменение API сначала делается в доке, а уже потом в коде (в идеале - путём кодогенерации из доки).
А потом оказалось что сгенерировали что-то не то. Или требования изменились или просто ошиблись. Всякое бывает. Переделали конечно как надо. А вот дока все это время находится в непонятном состоянии. До ее исправления пройдет неизвестное время. И чем сложнее процесс этого изменения тем больше это время.
Вы только то поставили всю компанию в зависимость от одного человека. При этом того кто вероятно не в курсе конкретики того что в проде крутится.
Всё верно. Так и задумано. Потому что необходимость что-то чинить руками в проде - это не нормально, и если до этого дошло, то необходимо эскалировать проблему до начальства. И единственный способ это гарантировать - если без начальства на прод никто зайти не сможет в принципе.
При необходимости начальство кому-то откроет временный доступ, и кто именно будет руками это чинить - уже не так и важно. Важно, что свободный доступ к проду у разработчиков отсутствует, и что если он всё-таки понадобился - это не пройдёт незаметно для начальства.
Всё верно. Так и задумано
После этого на бизнесе можно ставить крест. Бизнес зависящий от одного человека нестабилен по определению. Мерфи говорит нам что проблемы будут именно в тот момент когда этот человек уехал на рыбалку в Сибирь и будет 4 дня без любой связи.
Важно, что свободный доступ к проду у разработчиков отсутствует, и что если он всё-таки понадобился - это не пройдёт незаметно для начальства.
Про незаметность я ничего никогда не говорил. Логи, аудит, возможно даже тикеты. Это хорошие практики одобренные всеми аудиторами.
Когда надо у кого-то что-то лично просить заметная часть разработчиков предпочтет сделать все чтобы этого не делать. Люди так устроены. Проблемы будут всеми силами заметаться под ковер, лишь бы не ходить и не просить кого-то. Особенно если проблема произошла около 4 утра по времени этого начальника которого надо просить.
Считается хорошей практикой дать доступы, дать красные кнопки вида "вот этот артефакт положить в прод вот сюда немедленно" и писать логи всех действий. Возможно зажигая мониторинги безопасников. Тут я не в курсе как это у безопасников делать принято.
После решения проблемы провести хотя бы внутренний разбор что сломалось, как починили и что будет сделано чтобы это не повторилось. Уровень разбора зависит от уровня проблемы и насколько сильно она зааффектила бизнес и деньги.
Бизнес зависящий от одного человека нестабилен по определению.
В моём варианте никакой зависимости нет. Есть кто-то ответственный, мимо которого доступ к проду получить нельзя. Но на его личность при этом ничего не завязано, и ответственного можно в любой момент поменять. Звонки в 4 утра - не проблема, если случаются раз в 2 года. А если руками в прод надо лазить чаще - то проблема совсем в другом.
Логи, аудит, возможно даже тикеты.
Да, можно и так, конечно. Но есть проблема: это всё слишком легко игнорировать. В том смысле, что можно руками трогать прод хоть дважды в день, всё будет логироваться, но никому до этого не будет дела. Да, эти логи помогут когда-нибудь в будущем всё это отследить, но проблема "разработчикам регулярно надо руками чинить прод" есть уже сейчас, и сейчас её никто (из тех, кто должен в этот момент вмешаться и устроить разборки причин происходящего) не замечает.
Более того. Всю эту инфраструктуру дающую доступ к проду с соответствующим аудитом - ещё надо построить. (Ни на одном мелком-среднем проекте я такой не встречал. А вот прод на этих проектах есть…) И строить её будут только если в ней есть необходимость. А необходимости такой быть не должно! И если она всё-таки есть, то у нас проблема где-то в другом месте, а вовсе не в отсутствии этой инфраструктуры.
В моём варианте никакой зависимости нет. Есть кто-то ответственный, мимо которого доступ к проду получить нельзя.
Эти два предложения прямо противоречат друг другу. Вы уж определитесь.
Но на его личность при этом ничего не завязано, и ответственного можно в любой момент поменять.
Развиваем идею чуть дальше и получается что у всех разработчиков есть доступ. Нажатие кнопки взять на себя ответственность ничего не меняет и в общем даже не нужно. Логин под рутом на сервер можно считать нажатием такой кнопки.
Да, эти логи помогут когда-нибудь в будущем всё это отследить, но проблема "разработчикам регулярно надо руками чинить прод" есть уже сейчас, и сейчас её никто (из тех, кто должен в этот момент вмешаться и устроить разборки причин происходящего) не замечает.
Тут надо что-то написать про взаимоотношения в команде и софт скилы руководителя. Это отличные темы для обсуждения на совещаниях. Надо выстроить работу так чтобы люди не скрывали и рассказывали что они делали в проде руками.
Дальше как обычно. Тикет чтобы больше по этой причине не надо было, исполнитель и исправление причины в рабочем порядке.
Всю эту инфраструктуру дающую доступ к проду с соответствующим аудитом - ещё надо построить. (Ни на одном мелком-среднем проекте я такой не встречал. А вот прод на этих проектах есть…) И строить её будут только если в ней есть необходимость
Именно. Мелко-средним проектам это все не нужно, а вот чинить прод им надо чаще. Больше прав, личного подхода и как это называют "атмосфера стартапа". Это нормальный этап развития бизнеса.
Проблемы тут нет. Это нормальная плата за гибкость и быстроту развития. Надо ее просто принять и платить. Когда/если бизнес вырастет, то значит пора строить инфраструктуру аудита, безопасников и все вокруг. Когда именно это надо делать видно только местному высокому руководству. Это тоже нормальная плата за вырастание бизнеса. Ее просто надо заплатить когда придет время.
Строить небольшой бизнес по критериям банка не выйдет. Вас обойдут ребята с прямым доступом в прод и игнорированием всей безопасности. Просто за счет более быстрого развития и большей гибкости. Ваш бизнес будет полностью безопасным и мертвым.
Я прекрасно знаком с описываемым Вами подходом. И даже сам так делал лет 17 назад.
Но я не согласен с тем, что это единственный рабочий подход. И с тем, что иной подход замедлит разработку. Наоборот. По моим наблюдениям разработку замедляет как раз наличие доступа к проду - чинить так быстрее, только вот потом приходится разгребать последствия ручного ковыряния прода, которые вылезают далеко не сразу, и времени это съедает довольно много.
Ваш подход тоже имеет право на жизнь. Главное понимать когда именно.
Если вы делаете Google ID, то да. Доступы минимизируем максимально. Звонки руководителям в 4 утра считаем неизбежным злом, выдаем спутниковые телефоны всем ответственным. Платим людям за это все. И миримся с замедлением разработки. Это нормальная плата за максимизацию безопасности.
А вот если вы делаете очередной интернет магазин или очередную CRM то зачем все это? Вам надо выжить в конкуренции с другими 100500 магазинами. Платить за максимизацию безопасности нет смысла, вероятность погибнуть проиграв конкуренцию заметно выше.
По моим наблюдениям разработку замедляет как раз наличие доступа к проду - чинить так быстрее, только вот потом приходится разгребать последствия ручного ковыряния прода, которые вылезают далеко не сразу, и времени это съедает довольно много.
А вот тут я не согласен. Нужен процесс разгребания того что делалось в проде руками. Этот процесс может быть разным. Зависит от конкретного этапа развития бизнеса. Степень его формализации тоже может быть разной.
В стартапе на 5 разработчиков процесса "в пятницу за пивом на уровне байки рассказали" хватит.
В средне-крупном бизнесе регулярные совещания, логи и тикеты на исправление таких ситуаций. С отслеживанием повторов случаев когда по той же причине полезли руками править. Глобальная и вероятно недостижимая цель минимизации таких случаев.
Любые промежуточные варианты тоже возможны.
А вот если вы делаете очередной интернет магазин или очередную CRM то зачем все это?
Затем, что, как ни парадоксально, так писать быстрее. Реализация появляется чуть медленнее, но в сумме время разработки экономится за счёт меньшего количества проблем, багов и потерь времени на расследования инцидентов и отладку.
Конечно, если просто запретить доступ к проду - такого эффекта не будет, наоборот, всё станет хуже. Но в комплексе с рядом других процессов - ТЗ (и вообще documentation-first, включая доку на API с кодогенерацией), CI/CD, автоматизированные миграции БД, правильные юнит-тесты и немного интеграционных, обязательные и тщательные ревью - картина кардинально меняется.
Но в комплексе с рядом других процессов - ТЗ (и вообще documentation-first, включая доку на API с кодогенерацией), CI/CD, автоматизированные миграции БД, правильные юнит-тесты и немного интеграционных, обязательные и тщательные ревью - картина кардинально меняется.
Вы точно работали в чем-то небольшом и стартапоподобном? Или хотя бы в среднем, а конкурентном рынке?
Вот это все дает большую стабильность, жутко замедляет разработку, жжет море человекочасов и принципиально отсутствует в везде кроме больших корпораций. Это обычно преподносится как преимущество и атмосфера старпапа.
"в сумме время разработки " - всем кроме корпорацией не важно. Вероятность умереть через полгода больше. Надо быстрее релизиться сегодня. Что будет даже через год не знает никто.
PS: Исключения вроде CI/CD могут быть, я в целом про картину.
Точно работал, и сейчас в таком работаю.
По моим наблюдениям "в сумме время разработки" с этими процессами догоняет разработку в стиле "быстро-грязно" за 2-3 месяца, если небольшая команда (4-5 человек) уже умеет работать по этим процессам, и через полгода, если не умеет и учится на ходу. Цифры относительно с потолка, разумеется, потому что одновременно в обоих подходах один и тот же проект никто не делал, но порядок примерно такой. Для стартапа это вполне приемлемо.
И дело не в стабильности или безопасности, а в том, на что конкретно тратится время разработки.
При подходе "быстро-грязно" код пишется очень быстро, но зато много времени уходит на переделки, на отладку странных проблем, на хаки и на багфиксы (если задача не просто написать прототип, а чтобы оно ещё и работало в проде с реальными юзерами). А самое неприятное, что это вот "много времени" занимает чем дальше, тем больший процент общего времени разработки. Чтобы эту проблему решить начинают тратить время ещё и на выделенный рефакторинг, но это только всё усугубляет - не в смысле качества кода, а в процентном отношении времени, которое пишутся новые фичи, и времени, которое уходит на то, чтобы заставить их относительно корректно работать.
В одном из выступлений дяди Боба был отличный пример: любую задачу можно сдать во-время, просто закоммитив то, что готово (у него в примере это был вообще пустой файл без кода). А на вопрос тестировщиков "а где же фича?" ответить "это баг! сейчас буду чинить…" и тем самым получить дополнительное время на разработку.
Причина высоких временных затрат при подходе "быстро-грязно" заключается в том, что хоть и можно что угодно написать очень быстро и без полного понимания что мы пишем и как оно должно работать… но вот пофиксить это столь же быстро уже не получается - чтобы проблему пофиксить её всё-таки приходится сначала найти, а потом понять - и это внезапно требует больше времени (и понимания), чем требовало написание изначального кода.
Поэтому истинно высокая скорость разработки "быстро-грязно" наблюдается исключительно при написании прототипов, в которых необходимость делать багфиксы - это скорее исключение для совсем уж критичных багов. Но если прототип после этого не выбрасывают, а ставят в прод, что довольно частое явление, то скорость разработки тут же сильно падает. Точнее, как. Субъективно воспринимаемая командой разработчиков скорость остаётся прежней, они продолжают фигачить быстро-грязно, как и до прода. Но при этом сильно падает скорость реализации новых бизнес-фич - особенно если считать фичу реализованной не в момент мержа в мастер, а тогда, когда по ней перестали приходить серьёзные багрепорты и ей стало возможно реально пользоваться в проде.
При другом подходе картина совсем иная: код пишется не так быстро (доку сначала надо написать, API спроектировать до кода, а, главное, понять что же мы пишем и как оно должно работать!), но зато на порядок меньше времени уходит на переделки, отладку и багфиксы. А ещё лучше то, что время на переделки, отладку и багфиксы практически не увеличивается по мере роста проекта. Поэтому, если измерять время разработки по скорости появления полноценно рабочей бизнес-фичи в проде - этот подход очень быстро обгоняет быстро-грязный даже в стартапах.
Скорее всего, Вы в это не верите. :) И я даже догадываюсь почему: в тех проектах, которые Вы наблюдали лично или слышали от знакомых, попытка писать нормально заканчивалась обычно очень плохо: куча времени уходила непонятно на что и стартап просто не доживал до прода. Так происходило потому, что всё вышеописанное нужно уметь делать, а большинство разработчиков этому никогда не учили и даже не говорили, что всё это нужно делать в принципе. Чтобы это работало на проекте нужен нормальный архитект, нужно понимать как писать ТЗ чтобы это не было тратой времени на никому не нужные и неактуальные документы, как писать юнит-тесты чтобы они ускоряли разработку а не съедали время разработки впустую… Если всего этого нет - попытка писать так, как я предлагаю - ничем хорошим для проекта не кончится.
BTW, не поймите меня неправильно: я вовсе не утверждаю, что стартап написанный в режиме быстро-грязно - это плохо для бизнеса. Слишком много примеров обратного. Я лично делал аудит некоторых крупных финтех-проектов когда их кто-то купил, и видел там в коде такое… волосы дыбом стояли. Но как стартап - проекты были вполне успешны, раз у них было много пользователей и их кто-то купил. Я утверждаю совсем иное: что если "умеючи", то писать чисто получается быстрее, чем "быстро-грязно", даже для стартапов.
Дык все уже придумано давно и инструменты это поддерживающие были еще в прошлом веке (типа PowerDesigner, ERwin и тд). Тот же Sparx EA позволяет сколь угодно сложные взяимосвязи моделировать и я работал в паре контор, где в нем были сделаны огроменнейшие модели всех сервисов, систем и интерфейсов между ними. Проблема, что с waterfall это еще как-то работает, а вот с agile я уже такого не видел. Ну и плюс огромная трудоемкость поддержания всего этого в адекватном состоянии.
Благодарю за коммент.
Приходится работать со Sparx EA и ER Studio DA (в Sparx схема и в ER Studio рисуем ERD всей банковской системы штатов). Неудобный зоопарк.
Функционал Sparx и ER Studio - не то, что я описывал, не покрывает нужный функционал.
Помимо этого, эти виндовые продукты довольно тяжелые, не поддерживают многопользовательский доступ и модификацию.
Насчет ERwin - был хорош в 90ые годы, да и Sparx тоже архаичный. :)
Повторюсь: я про БД с метаданными, описывающую схему, сервисы, процессы, тестовые данные, моки сервисов и симуляцию процессов.
К этой БД прикручивается необходимый функционал.
В текущем проекте большая часть вышеописанного реализована и результаты продуктивности высокие. Над остальными работаем.
С таким подходом микросервисы не выглядят unmanageable, хоть и значительно сложнее монолитов.
Давайте так. Любое решение - это боль (со временем). Микросервисы просто позволяют ощутить это гораздо раньше, это своего рода мультипликатор "технической кармы".
сколько орехов нужно собрать, чтобы получилась целая куча.
Четыре. Не благодарите.
Споры "монолит vs микросервисы" и топики "как нам распилить монолит" возникают только по одной причине - попытке следовать каким то очередным айти-церемониям, без понимания их сути. К сожалению в нашей области это стало происходить сплошь и рядом.
Нельзя "создавать микросервисную архитектуру" и "распиливать монолиты". Если вы начинаете проект, в котором пока 2 сервиса и 3 таблицы в базе - не надо городить микросервисы, надо сделать проект максимально быстрым и простым способом. И только когда вы увидите что все хорошо, но вот в каком то конкретном месте просадка по скорости или ограничение по архитектуре или есть возможность эту часть отдать на оутсорс другой команде - вот ровно тогда эту часть инкапсулируйте, выделите в отельный репо, распишите для нее свое хранилище, права, деплой, тесты и т.п. А остальное пусть работает как работает.
Все беды от сеньоров с двухлетним стажем, с кашей из теории в голове, с горящими глазами и желанием попробовать хоть что то из прочитанного в интернете.
Вы всё верно сказали. Только забыли упомянуть, что основная проблема монолитов вовсе не тормоза, архитектура или невозможность аутсорсить куски функционала. Основная проблема монолитов - это сложность. Поскольку всё связано со всем, любая фича лазит в эти 3 таблицы в базе, то становится сложно отслеживать все связи в голове, теряется понимание общей картины и понимание архитектуры. Это происходит не в первые месяцы разработки, но происходит обязательно. В первые месяцы это позволяет писать быстрее, но за это приходится расплачиваться сильным замедлением разработки потом. А чтобы этого избежать нужно внедрить модульность, в том или ином виде - не обязательно микросервисами, но обязательно так, чтобы любой фиче уже было нельзя лазить во все 3 таблицы. И контролировать это должен непосредственно или язык, или инструменты (напр. линтеры), или ОС - в общем кто-то, кого не получится отключить или как-то незаметно обойти при желании реализовать срочный хак.
Уже сто раз обсуждали - микросервисы никак не уменьшают сложность, они поднимают ее на уровень межсервисного взаимодействия.
Да. Но это если смотреть на проект в целом. А если смотреть по командам, то сложность разработки одного микросервиса сильно ниже получается, чем монолита. Да, это компенсируется выросшей сложностью на уровне архитектуры проекта. Т.е. разработчикам жить стало намного легче, а архитекту наоборот, тяжелее. Разработчиков сильно больше, чем архитектов, квалификация у них сильно ниже, чем у архитектов - поэтому для компании обычно такой размен выгоден.
Можно подытожить: без проработки архитектуры получается плохая архитектура. Как следствие, дорогая разработка и сопровождение.
Микросервисы и неизбежная боль?