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

Рейтинг: 5

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

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

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

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

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

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

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

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

Такая выборка подсказывает вывод, который трудно назвать глупым. Netflix успешен; Netflix построен на микросервисах; значит, микросервисы ведут к успеху. Перед нами были выступления инженеров компании, которая держала огромный трафик, открывала код своих инструментов и подробно рассказывала, как переживает отказы. Чтобы проверить вывод, понадобились бы ещё две группы: компании с другой архитектурой и тем же успехом и компании с той же архитектурой, но без успеха. По той же логике отбора первые редко становились докладами об архитектуре, а вторые почти никогда. При такой выборке силлогизм выглядит не натяжкой, а самым экономным объяснением.

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

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

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

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

16 января 2007 года Netflix запустил просмотр фильмов через интернет на персональных компьютерах. Сервис предлагал около тысячи фильмов, работал только в Windows и не требовал доплаты от тех, кто уже получал DVD по почте, но ограничивал просмотр месячным лимитом часов, который зависел от тарифа. Основным делом компании оставалась рассылка дисков. Микросервисов у неё не было: описывая в 2016 году завершение переезда в облако, сама компания называет исходную точку монолитным приложением, а конечную — сотнями микросервисов. Переход начался после сбоя базы данных в августе 2008 года и закончился в январе 2016-го, то есть занял около семи лет. Архитектура, которую мы видели на сценах в середине 2010-х, была итогом этих лет, а не их началом. Тем самым Netflix укладывается в наблюдение Фаулера из «MonolithFirst».

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

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

2.3. Книги без контекста

В феврале 2015 года издательство O’Reilly выпустило книгу Сэма Ньюмана «Building Microservices» — «Создание микросервисов». Ньюман работал над ней в 2014 году, когда вышла статья Льюиса и Фаулера, и для многих команд книга стала первым и главным справочником по новому стилю. Устроена книга так, как устроен любой хороший справочник. Первая глава объясняет, что такое микросервисы и чем они полезны. Дальше идут одиннадцать глав, и почти все они о том, как с микросервисами работать: как моделировать сервисы и связывать их между собой, как выделять их из монолита, развёртывать, тестировать, следить за их работой и защищать, что меняется на большом масштабе. Среди этих глав есть и глава о роли архитектора, и глава о законе Конвея и проектировании систем, а последняя сводит сказанное воедино.

О цене Ньюман пишет с первой главы: её последний раздел перед итогами называется «No Silver Bullet» — «Серебряной пули нет». Микросервисы, предупреждает Ньюман, не бесплатный обед и не универсальное средство: они приносят с собой всю сложность распределённых систем. Каждая компания, организация и система устроены по-своему, и подойдут ли им микросервисы, зависит от многих факторов. К этому Ньюман возвращается в последней главе, в разделе «When Shouldn’t You Use Microservices?» — «Когда микросервисы не нужны»: для нового продукта он советует сначала рассмотреть монолит. Упрёк «книга не предупреждала» опровергается и первой её главой, и последней.

Со временем Ньюман писал об этом всё прямее. В ноябре 2019 года вышла его книга «Monolith to Microservices» — «От монолита к микросервисам», о переходе от одной архитектуры к другой. В ней он настаивал, что микросервисы — не цель и что само их наличие ничего не выигрывает. Переходить к ним стоит осознанно, ради того, чего нельзя добиться с нынешней архитектурой. В марте 2020 года на конференции QCon в Лондоне он, в передаче журналиста The Register, говорил, что микросервисы — не выбор по умолчанию и что половине своих клиентов он советовал обойтись без них.

Во втором издании «Building Microservices», вышедшем в августе 2021 года, позиция записана без смягчений. Уже в предисловии Ньюман замечает, что для многих микросервисы стали архитектурным выбором по умолчанию и что оправдать это трудно. В первой главе монолит назван вполне законным выбором, а затем — «на мой взгляд, разумным выбором по умолчанию» (the sensible default choice). Сам Ньюман, по его словам, ищет причину, которая убедила бы его взять микросервисы, а не причину от них отказаться. Там же есть раздел о тех, кому микросервисы могут не подойти (Whom They Might Not Work For): для новых продуктов и стартапов они часто плохой выбор, и чем меньше команда, тем заметнее цена. Эту цену, замечает Ньюман, называют налогом на микросервисы (microservice tax), и он прикладывает её к команде из пяти человек: если один из пяти занят этой инфраструктурой, много ценного времени уходит не на продукт.

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

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

В этой пропорции нет умысла. Книга о том, как строить, не может не состоять в основном из строительства. Справочник, который на каждой странице сомневался бы, стоит ли строить, был бы другой книгой, и практического руководства у отрасли тогда бы не было. Но у пропорции есть смысл, которого автор в неё не вкладывал: объём сообщает, о чём главный разговор. Из книги выносят ощущение, что вопрос в том, как, а не в том, стоит ли.

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

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

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

Ещё сильнее тот же эффект у каталогов паттернов. С 2014 года Крис Ричардсон ведёт сайт microservices.io, где собирает то, что сам называет языком паттернов. В октябре 2018 года в издательстве Manning вышла его книга «Microservices Patterns» — «Паттерны микросервисов» — с 44 паттернами. Паттерн здесь — описанный приём проектирования, у которого есть имя и диаграмма: отдельная база данных у каждого сервиса, сага для операции, которая затрагивает несколько сервисов, шлюз для внешних клиентов перед всеми сервисами. Имя делает приём предметом разговора: на обсуждении архитектуры достаточно сказать «база на сервис», и все понимают, о чём речь. Диаграмма превращает его в чертёж, который можно перенести в свою систему. Приём с именем и чертежом приобретает вес стандарта: раз его внесли в каталог и нарисовали, значит, так принято.

Сам каталог стандартом себя не объявляет. Паттерны на microservices.io описаны по общей форме: контекст, задача, силы, которые приходится уравновешивать, решение и то, что получится в итоге, с достоинствами и недостатками. У отдельной базы на сервис недостатки названы прямо: трудно проводить бизнес-операции, которые охватывают несколько сервисов, трудно строить запросы по данным из разных баз, сложно управлять множеством баз. В том же каталоге паттерном описана и монолитная архитектура. Взаимодействия в ней проще понять и отладить, вызовы локальны, операции обычно укладываются в транзакцию одной базы. Там же сказано, что недостатки монолита становятся серьёзнее, когда растут приложение и число команд, которые его разрабатывают.

Но в разговор об архитектуре попадает имя, а не раздел о том, что получится в итоге. В проектном документе остаётся строка «база на сервис», а три её недостатка туда не переходят, как и замечание из описания монолита о числе команд. Имя паттерна занимает два слова, описание его цены — абзац.

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

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

2.4. Тетралогия хайпа

В августе 2003 года издательство Addison-Wesley выпустило книгу Эрика Эванса «Domain-Driven Design: Tackling Complexity in the Heart of Software» — «Предметно-ориентированное проектирование: как справиться со сложностью в самом сердце программы». Книга была не о сетях. Эванс писал о том, как построить модель сложной предметной области и как разработчикам и знатокам этой области говорить на одном языке. Подход получил короткое имя по заголовку книги — DDD. До статьи Льюиса и Фаулера оставалось десять с половиной лет.

Одно из главных понятий книги — bounded context. В русских переводах его называют ограниченным контекстом, но в речи инженеров прижилось английское название. Мысль за ним простая: у модели есть область, внутри которой она верна, и эту область нужно очертить явно. Эванс предлагал задавать её границы «с точки зрения организации команд, использования в определённых частях приложения и физического воплощения, такого как кодовые базы и схемы баз данных» (team organization, usage within specific parts of the application, and physical manifestations such as code bases and database schemas). Команда в этом определении уже есть. О сети и единице развёртывания в нём не сказано ничего.

Легче всего увидеть такую границу на одном слове. Возьмём условную систему гостиницы. Для бронирования «номер» — это категория, вместимость и цена за ночь на выбранные даты. Для хозяйственной службы «номер» — конкретная комната на третьем этаже, которую нужно убрать до двух часов дня. Слово одно, моделей две, и попытка описать обе одним классом даёт объект, наполовину чужой каждой из сторон. Bounded context разрешает словам значить разное по разные стороны границы модели и требует, чтобы место перехода было названо явно.

Через десять с лишним лет это различение встретилось с новым вопросом. Статья 2014 года описывала сервисы, нарезанные по возможностям бизнеса, и тому, кто начинал резать, нужно было знать, где проходит линия. Ответ нашёлся в той же статье: в разделе о данных Льюис и Фаулер ссылались на bounded context Эванса. Они отмечали, что делить предметную область на контексты полезно и для монолитной, и для микросервисной архитектуры, но между границами сервисов и контекстов есть естественное соответствие.

10 июня 2014 года, через три месяца после статьи, Google представил Kubernetes. Версия 1.0 вышла 21 июля 2015 года, через полтора месяца после того, как на сайте Фаулера спорили, с чего начинать новую систему. В тот же день Google объявил о передаче проекта создаваемому фонду Cloud Native Computing Foundation (CNCF). Оркестратор сделал запуск ещё одного сервиса будничным делом: каждая развёрнутая часть системы получала свой контейнер и свой адрес в сети.

Цепочка DDD, bounded context, микросервис, Kubernetes выглядит так, будто каждый шаг продолжает предыдущий. Но на каждом шаге слово «граница» меняет смысл. Bounded context — граница модели и языка: по разные её стороны «номер» значит разное. Граница команды — организационная граница: она отделяет тех, кто договаривается друг с другом каждый день, от тех, с кем договариваются через контракт, и по закону Конвея система стремится её повторить. Микросервис — граница процесса и развёртывания: отдельная программа, которую собирают, выпускают и откатывают сама по себе. Сетевой вызов (network call) — физическая граница, и налог распределённости начисляется именно на неё: на сетевую границу, место, где вызов функции (function call) заменён сетевым вызовом.

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

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

Цепочка склеила четыре границы в одну: «один bounded context = одна команда = один deployable = один сетевой адрес», где deployable — единица развёртывания, то, что выпускается как одно целое. У каждого равенства по отдельности есть основание. Контекст и команду связывает уже определение Эванса; команде, которой нужна независимость, удобно выпускать свой код самой; развёрнутая часть системы в Kubernetes получает адрес по умолчанию. Но первое равенство верно, когда команд много, второе — когда им действительно мешают общие выпуски, а третье описывает свойство инструмента, а не требование задачи. Составленные вместе, они дают равенство, которого не было ни в одном звене: контекст равен сетевому адресу. Логическая граница приравнивается к физической.

С этого момента вопрос о физике системы решается на языке моделирования. Число сетевых границ задаёт уже не число команд, которым нужна независимость, а то, насколько подробно мы разобрались в предметной области. Чем глубже анализ, тем больше контекстов, и каждый новый контекст по формуле означает ещё один сетевой адрес. Хорошее моделирование начинает увеличивать счёт за инфраструктуру, хотя ни книга Эванса, ни статья 2014 года не превращали число контекстов в число сервисов. Именно эту подмену в 2023 году назовут исследователи Google в статье «Towards Modern Development of Cloud Applications» — «К современной разработке облачных приложений». По их словам, микросервисы смешивают логические границы, то есть то, как написан код, с физическими — тем, как он развёрнут.

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

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

Соответствие сервиса контексту поддерживал и сам автор понятия. В 2015—2016 годах Эванс выступал в Лондоне и Берлине с темой «DDD & Microservices: At Last, Some Boundaries!» — «DDD и микросервисы: наконец-то границы». По отчётам InfoQ, он видел в микросервисах, возможно, лучшую среду для DDD за всю его историю, потому что они дают настоящие границы, а соответствие одного сервиса одному контексту считал хорошим вариантом хотя бы для первого приближения. В 2019 году на DDD Europe он говорил на тему «Language in Context» — «Язык в контексте». Там, в пересказе того же InfoQ, он назвал отождествление микросервиса с bounded context упрощением, а сами микросервисы — одновременно самой большой возможностью и самым большим риском за долгое время. Уточнение шло в другую сторону: контекст может охватывать кластер сервисов, спроектированных вместе, а может не содержать сервисов вовсе, только сообщения, схемы и протоколы. Мысль, что контекст может быть меньше процесса и жить модулем рядом с другими, — уже позиция этой книги.

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

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

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