Микросервисы без иллюзий. Арифметика архитектурного решения - читать онлайн бесплатно, автор Сергей Кирницкий, ЛитПортал
Микросервисы без иллюзий. Арифметика архитектурного решения
Добавить В библиотеку
Оценить:

Рейтинг: 5

Поделиться
Купить и скачать

Микросервисы без иллюзий. Арифметика архитектурного решения

Год написания книги: 2026
На страницу:
3 из 5
Настройки чтения
Размер шрифта
Высота строк
Поля

Второе понятие пришло с другой стороны. В 2019 году Мэттью Скелтон и Мануэл Паис в книге «Team Topologies» («Топологии команд») перенесли на команды понятие когнитивной нагрузки (cognitive load). Его источник — теория психолога Джона Свеллера, где когнитивная нагрузка — общий объём умственных усилий, которые занимают рабочую память человека. Команда, по Скелтону и Паису, тоже способна удерживать в голове лишь ограниченную часть системы. Поэтому подсистема, которой владеет команда, не должна вырастать за пределы этой нагрузки.

Вместе с арифметикой Брукса это понятие ставит границе сервиса два предела. Арифметика Брукса ограничивает её снаружи: чем больше сторон должны договориться об изменении, тем дороже каждое изменение. Когнитивная нагрузка ограничивает её изнутри: команда не может надёжно владеть большим, чем способна понимать. Граница, проведённая по линии между командами, учитывает оба предела сразу. Из этого следует, что главная переменная здесь — не число строк и не трафик, а число команд, которым нужна независимость друг от друга.

Слово «закон» здесь обманчиво. Закон Конвея — эмпирическое наблюдение, а не закон физики. Сам Конвей вспоминал, что сначала отправил статью в Harvard Business Review и журнал её отклонил: автор, по мнению редакции, не доказал свой тезис. Брукс к собственным формулировкам относился так же трезво. Знаменитый закон Брукса — добавление людей в запаздывающий программный проект задерживает его ещё сильнее — он сам предварял словами о возмутительном упрощении. Даже формулировка закона Конвея дошла до читателей с поправкой: Брукс, цитируя статью, написал «системы» там, где у Конвея стоят «проекты».

Проверить закон Конвея исследователи пытались. Одна из самых известных проверок — работа Алана Маккормака, Карлисс Болдуин и Джона Руснака в журнале Research Policy в 2012 году. Авторы проверяли так называемую зеркальность (mirroring) — соответствие структуры продукта структуре организации. Они сравнили пять пар программных продуктов с одинаковым назначением: в каждой паре один продукт делала коммерческая компания с тесно связанной командой, другой — слабо связанное сообщество открытого кода. Во всех парах продукт слабо связанной организации оказался заметно лучше разделён на независимые части. По тому, насколько изменение в одном компоненте способно задеть другие, разница, по данным авторов, доходила до шести раз.

Это сильное подтверждение, но подтверждение связи, а не механизма: исследование не показывает, что устройство организации порождает устройство кода. Можно предположить и обратное направление: люди, которые пишут слабо связанный код, легче работают слабо связанными группами. Можно предположить и общую причину — например, сам способ, которым открытые проекты принимают правки от множества независимых участников. Поэтому книга использует закон Конвея как объяснительную модель, а не как доказательство: он объясняет, почему истории Amazon, Netflix и Uber похожи, но не заменяет данных о каждой из них.

У закона есть и обратное прочтение: по архитектуре можно восстановить организацию, которая её создала. Тридцать сервисов с контрактами между ними — рисунок, который по закону Конвея оставила бы организация из многих команд, каждой из которых нужно договариваться с соседями через контракты. Такая организация покупала бы каждой границей то, что граница умеет покупать: право менять код за контрактом без переговоров. Но если архитектура отражает организацию, то 30 сервисов у одной команды из 12 человек отражают организацию, которой не существует.

Цену такая команда при этом платит полностью. Каждую границу по-прежнему нужно описать контрактом, изменения на обоих её концах — согласовать, а сервисы — развёртывать в правильном порядке. Но по обе стороны границы стоят одни и те же люди, и переговоры, от которых граница должна была избавлять, им вести не с кем, кроме самих себя. Граница сервиса без границы команды — это цена без покупки.

1.5. Общая черта

Если поставить рядом числа масштаба из трёх историй, они окажутся разного рода. У Amazon начала 2000-х — одно приложение Obidos, которое меняли все вместе. Работали над ним, по рассказу Бригхэма, сотни разработчиков. У Uber — рост примерно с 200 до 2 000 человек за полтора года, по словам Рэнни в 2016 году. У Netflix число инженеров не опубликовано, зато известно, что с 2008 по 2016 год объём просмотра вырос на три порядка. Два числа из трёх описывают людей, одно — трафик.

Числа о людях можно перевести в меру, которую даёт формула Брукса. Двести человек — это 19 900 возможных каналов, две тысячи — 1 999 000, почти два миллиона. За полтора года людей в Uber стало вдесятеро больше, а каналов — примерно в сто раз. Сотни инженеров Amazon дают десятки тысяч каналов и больше. Сами по себе эти числа говорят только о размере, а не о пороге. Судя по собственным описаниям обеих компаний, к моменту перестройки они упёрлись в предел координации: время всё больше уходило на ожидание согласований, а не на сам код.

Третье число описывает не людей. История Netflix начинается с отказавшей базы, а не с очереди в общем коде. Техническая причина пришла первой, но организационный итог оказался тем же, что у Amazon и Uber.

У такой перестройки была цена, и часть её участники описали сами: поиск владельца сбоя через цепочку сервисов, привычку нарочно ломать собственную систему, трассировку запроса через четыре языка. Другие издержки заложены в самом устройстве. Вызов функции (function call) стал сетевым вызовом с его задержками; изменение, которое укладывалось в одну транзакцию одной базы, стало распределённой транзакцией; данные, жившие в одной таблице, пришлось дублировать между сервисами. Для компаний того масштаба всё это было приемлемой ценой. Они покупали организационную скорость, которую при таком числе людей иначе было не получить.

Покупка у трёх компаний была одна и та же, хотя пришли они к ней разными путями. В Amazon, по словам Фогельса, у каждого сервиса была своя команда, которая отвечала за него целиком, вплоть до эксплуатации. В Uber новая команда заводила свой сервис, чтобы не ждать очереди в общем коде. У Netflix, вероятно, каждый независимый компонент получал своего владельца — небольшую команду. Во всех трёх случаях, насколько позволяют судить источники, граница сервиса легла по границе команды и стала границей переговоров.

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

Типичная инженерная команда продуктовой компании выглядит иначе: в ней десятки инженеров. Прямых отраслевых данных о численности таких команд нет, поэтому это пример, а не статистика. Косвенно его поддерживает Stack Overflow Developer Survey 2025 года: около 38% ответивших работают в компаниях меньше чем на 100 сотрудников, не считая фрилансеров. Это размер компании, а не инженерной команды, и опрос говорит только о тех, кто сам решил в нём участвовать. Но в компании меньше чем на сто человек тысячи инженеров нет по определению. По отчёту JetBrains 2022 года, большинство опрошенных разработчиков работает над проектами в командах из 2—7 человек.

По той же формуле команда от десяти до сорока пяти инженеров — это от 45 до 990 каналов, а не полмиллиона. На таком масштабе автор изменения ещё знает всех, кого оно заденет, и согласование остаётся разговором, не превращаясь в процедуру с очередью. Ближе к сотне инженеров это начинает меняться: каналов становится 4 950, и людей уже делят на несколько команд. Но и тогда каналов примерно в сто раз меньше, чем у тысячи. Предел, до которого дошли Amazon и Uber, лежит выше, там, где инженеров уже сотни, и такая компания к нему только подходит.

Сами Amazon и Uber когда-то тоже были по эту сторону предела. Одно приложение Obidos, обращавшееся к базе данных, и монолит, написанный для одной услуги в одном городе, были разумным выбором, пока людей было немного. Предел появился вместе с ростом, а не с первого дня.

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

То, что делало решение точным, — число людей, которым нужна независимость друг от друга, — в самом решении не видно. Снаружи видны сервисы и интерфейсы, Chaos Monkey и Hystrix в открытом коде, AWS как услуга, которую может купить любой. Причина — предел координации — осталась внутри организаций, которые заплатили цену: в их штатном расписании, в ожидании согласований, в очередях на изменение общей схемы.

Это неравенство видно даже по источникам трёх историй. О сервисах и библиотеках компании писали сами — в постах, в описаниях репозиториев, в объявлениях о запуске, с датами и номерами версий. О пределе известно гораздо меньше: ни одна из трёх компаний сама не опубликовала, сколько у неё было инженеров. У Amazon вместо числа — «сотни» из пересказа доклада Бригхэма, Netflix число инженеров не публиковал, а рост Uber известен по конспектам доклада Рэнни. Само распоряжение Безоса стало известно потому, что пост Йегге по ошибке оказался публичным.

Отсюда следует вопрос об условии, на котором решение держалось у Amazon, Netflix и Uber. Сколько у вас инженеров?

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

Микросервисы начинались как организационный инструмент — способ дать сотням инженеров работать, не блокируя друг друга. Amazon, Netflix и Uber делали его под собственный предел, каждый по своей мерке, и платили за него сами. Инструмент был создан для операционной. Скальпель в руке хирурга и скальпель в ящике на кухне — один и тот же предмет.

Глава 2. Как решение мутировало в рецепт

Летом 2015 года на сайте Мартина Фаулера с разницей меньше чем в неделю вышли два текста с противоположными заголовками. В первом Фаулер советовал начинать новую систему с монолита. Во втором Стефан Тилков возражал ему на той же площадке. Спорили два инженера с большим опытом, и оба исходили из того, что распределённость стоит дорого. Спор шёл не в закрытой переписке: его мог прочитать любой, кто искал тогда слово «микросервисы».

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

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

Проще всего увидеть эту потерю на одном формате — 45-минутном докладе. В нём помещаются схема из сорока сервисов, график задержек, история ночного отказа и того, как с ним справились. Фразе «у нас это окупается, потому что у нас тысяча инженеров и отдельная команда платформы» хватило бы минуты. Но когда время на исходе, эту минуту сокращают первой. Доклад — формат, куда оговорки не помещаются, а в те годы именно доклады звучали громче всего.

2.1. Формализация

С 10 по 25 марта 2014 года на сайте Мартина Фаулера частями выходила статья «Microservices» — «Микросервисы», написанная им вместе с Джеймсом Льюисом. Название было коротким, задача — скромной. Авторы не предлагали новый способ строить системы. Они описывали то, что уже видели у нескольких команд и компаний, и сразу оговаривали: формального определения у этого архитектурного стиля нет, есть общие черты систем, к которым применяют это название. Не у каждой такой системы есть все черты, но авторы ожидали, что у большинства найдётся большинство.

Черт насчитали девять. Приложение собирается из сервисов, а не из библиотек внутри одного процесса: компонентизация через сервисы (componentization via services). Сервисы нарезаются по возможностям бизнеса, а не по техническим слоям, и команда вокруг такого сервиса сквозная — от интерфейса до базы. Команда владеет продуктом всю его жизнь и не уходит, сдав проект: продукты, а не проекты. Логика живёт в самих сервисах, связи между ними остаются простыми — умные конечные точки и простые каналы (smart endpoints and dumb pipes). Дальше шли децентрализованное управление, при котором команды сами выбирают инструменты, и децентрализованное управление данными: каждый сервис распоряжается своим хранилищем. Замыкали перечень автоматизация инфраструктуры, проектирование в расчёте на отказ (design for failure) и эволюционное проектирование, при котором систему меняют по частям.

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

Статья была наблюдением, а не рекомендацией, и авторы понимали разницу. Последний её раздел был озаглавлен вопросом, станут ли микросервисы будущим программной архитектуры, и ответ в нём звучал сдержанно. Опыт, писали Льюис и Фаулер, пока положительный по сравнению с монолитными приложениями, но истинные последствия архитектурных решений часто видны лишь через несколько лет. Для микросервисов, по их словам, «прошло недостаточно времени, чтобы вынести окончательное суждение» (not enough time has passed for us to make a full judgement). Свою позицию они назвали осторожным оптимизмом.

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

28 августа 2014 года вышла заметка «Microservice Prerequisites» — «Предпосылки для микросервисов». Её мысль уложена в первые строки: если у команды нет некоторых базовых умений, браться за микросервисы не стоит. Умений три. Нужно быстро получать серверы: новый сервер должен подниматься за часы, и хотя полной автоматизации на старте не требуется, без неё дальше не обойтись. Нужен базовый мониторинг, потому что множество слабо связанных сервисов ломается в боевой среде так, что в тестовой это трудно обнаружить. Нужно быстрое развёртывание: сервисов много, и каждый должен доходить до тестовой и боевой среды без долгих процедур, а конвейер развёртывания, по Фаулеру, должен занимать не больше пары часов.

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

13 мая 2015 года вышел самый прямой текст серии — «Microservice Premium», «Премия за микросервисы». Слово «премия» (premium) здесь значит надбавку к цене. Фаулер писал, что микросервисы вносят в систему собственную сложность и она ложится надбавкой на стоимость и риск проекта, причём такой, что часто приводит проекты к серьёзным трудностям. Отсюда главное правило заметки, выделенное в оригинале жирным: даже не рассматривать микросервисы, если система не слишком сложна, чтобы управлять ею как монолитом. Следующая фраза говорила ещё прямее: большинство программных систем следует строить как одно монолитное приложение.

К правилу прилагался график. По горизонтали — базовая сложность системы, по вертикали — продуктивность, две кривые — монолит и микросервисы. Пока система проста, дополнительный груз, которого требуют микросервисы, снижает продуктивность, и их кривая идёт ниже. С ростом сложности продуктивность монолита начинает быстро падать, а у микросервисов, где связанность меньше, падает медленнее, и где-то кривые пересекаются. График схематический: чисел на осях нет, и точку пересечения Фаулер за измерение не выдавал. Внизу стояла подпись, не менее важная, чем сами кривые: умение команды весит больше, чем любой выбор между монолитом и микросервисами.

В той же заметке Фаулер показывал, насколько разные вещи прячутся под одним словом. Среди команд, называвших свои системы микросервисными, он встречал и команду из 60 человек с 20 сервисами, и команду из четырёх человек с 200 сервисами. Он упоминал и то, что Technology Radar компании Thoughtworks к тому времени уже дал имя стремлению строить микросервисы там, где они не нужны, — «Microservice Envy», зависть к микросервисам.

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

Через три недели, 3 июня 2015 года, вышла заметка «MonolithFirst» — «Сначала монолит». Фаулер пересказывал в ней опыт, собранный у коллег. Почти все успешные истории микросервисов начинались с монолита, который стал слишком большим и был разделён. Почти во всех известных ему случаях, когда систему с нуля строили как набор микросервисов, она в итоге попадала в серьёзные трудности. Совет из заголовка касался очерёдности, а не запрета: сначала монолит, а разделение — когда он действительно станет слишком большим. Заметка честно называла свой предел: большинство знакомых Фаулера склонялись к этому подходу, но единодушия не было.

Раньше этих трёх заметок, 13 августа 2014 года, вышел текст, который связывал новое слово со старой книгой, — «Microservices and the First Law of Distributed Objects», «Микросервисы и первый закон распределённых объектов». В 2002 году в «Patterns of Enterprise Application Architecture», книге о шаблонах архитектуры корпоративных приложений, Фаулер сформулировал правило, которое назвал первым законом проектирования распределённых объектов: не распределяйте свои объекты. Через двенадцать лет он сам положил этот закон рядом с микросервисами — меньше чем через пять месяцев после того, как статья о девяти характеристиках вышла целиком. Важен здесь сам факт: о цене распределённости один из авторов описания писал задолго до того, как появилось слово «микросервисы».

Предупреждения не были монологом. 9 июня 2015 года, через шесть дней после «MonolithFirst», на том же сайте вышла статья Стефана Тилкова «Don’t start with a monolith» — «Не начинайте с монолита». Тилков был твёрдо убеждён, что начинать с монолита, как правило, неверно. Части монолита неизбежно срастаются — через общие доменные объекты, общую модель хранения, общие транзакции, — и разрезать его потом на независимые куски крайне трудно. Поэтому достаточно большую систему, считал он, разумнее делить сразу, при условии что предметная область известна очень хорошо. Это сильный аргумент: цена позднего разреза реальна, и тот, кто откладывает границы, потом платит за них дороже.

Важнее, что в главном Тилков соглашался с Фаулером: не стоит вносить в систему сложность дополнительной распределённости без очень веской причины. Если команда способна построить хорошо структурированный монолит, писал он, микросервисы ей, вероятно, вообще не нужны. И масштаб он оговаривал сам: если систему несколько недель пишут два человека, вполне возможно, что без дробления они обойдутся. Даже сторона, которая спорила за раннее деление, записала условие о размере. Спор шёл о том, с чего начинать, а не о том, есть ли у микросервисов цена: её признавали обе стороны. Несогласие не мешало и совместной работе. В «MonolithFirst» Фаулер благодарил Тилкова за замечания к черновику, а в нынешней версии статьи о девяти характеристиках стоят ссылки на оба текста.

Стоит назвать и пределы самих предупреждений. Это были не исследования, а заметки, основанные на наблюдениях, и Фаулер прямо писал, что свидетельств немного. И сама статья 2014 года не нуждается в защите: девять черт точно описывали практику, которая у своих владельцев окупалась. Но условие в текстах было записано — с датами, под ясными заголовками, в открытом доступе.

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

Разница слышна даже в грамматике. Льюис и Фаулер писали языком наблюдателя: у таких систем, как правило, есть эта черта, и не у каждой есть все. В прочитанном та же черта получила модальное слово «должен»: у каждого сервиса должна быть своя база, каждая команда должна развёртываться независимо, связи между сервисами должны быть простыми. Изменилось одно слово, и описание практики нескольких организаций стало требованием к любой.

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

2.2. Survivorship bias

В 1943 году статистик Абрахам Вальд работал в Statistical Research Group — исследовательской группе при Колумбийском университете, которая решала математические задачи для военных. Среди его работ того года — серия меморандумов о том, как оценивать уязвимость самолёта по повреждениям машин, вернувшихся с заданий. Материал для такой оценки был под рукой: на вернувшемся самолёте можно пересчитать пробоины и отметить, где их больше. Трудность заключалась в том, чего в этом материале не было. Самолёты, получившие попадания в уязвимые места, не возвращались, и их пробоин никто не видел.

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

Историю Вальда знают в основном по упрощённому пересказу. Знаменитая картинка — силуэт самолёта, усеянный красными точками, — восходит к иллюстрации, которую около 2005 года сделал для своих выступлений дизайнер Кэмерон Молл, а версия, разошедшаяся по сети, нарисована в 2016 году. Точки на обеих вымышлены. У самого Вальда были не картинка и не короткий совет, а восемь технических меморандумов с расчётами. Метод разбирали и спустя сорок лет: в 1984 году статистики Марк Мангель и Франсиско Саманьего подробно описали его в журнале Американской статистической ассоциации. Но суть рассуждения пересказ сохранил.

На страницу:
3 из 5