Прим. перев.: автор этой статьи — Ben Nadel, сооснователь и главный инженер InVision App Inc. Миссию своей команды, поддерживающей серверную инфраструктуру компании, он сам характеризует как «advocate for the users», т.к. её главная цель — гарантировать пользователям InVision «получение опыта, который они заслуживают». Его путь — яркая иллюстрация того, что микросервисы не серебряная пуля.
Если вы следите за мной в Твиттере, то наверняка заметили, что периодически я публикую победные твиты о возвращении одного из наших микросервисов в InVision обратно в монолит. Обычно эти твиты сопровождаются гифкой, в которой Танос вставляет последний Камень бесконечности в Перчатку бесконечности. Нахожу ее вполне уместной, поскольку воссоединение камней придает Таносу невероятную силу — так же, как воссоединение микросервисов придает силу мне и моей команде. Меня много раз спрашивали, почему я избавляюсь от микросервисов. Настало время поделиться своими мыслями по поводу этого путешествия в мире разработки веб-приложений.
Я не против микросервисов!
Хочу предельно ясно обозначить свою позицию и начать статью с заявления о том, что я не против микросервисов! Возвращение микросервисов в монолит вовсе не представляется мне этаким «крестовым походом». На самом деле вся идея в определении правильного размера монолита. По сути, я просто убираю очередную «болевую точку» для своей команды. Все затевается ради уменьшения числа проблем: иначе я бы не стал тратить время (и другие ресурсы) на подъем, перемещение и рефакторинг старого кода.
Каждый раз занимаясь этим, я рискую внедрить в код новые баги и сломать что-нибудь для пользователей. Слияние микросервисов обратно в монолит — хотя иногда и волнующее, но всегда пугающее занятие; этакий мастер-класс по планированию, снижению рисков и тестированию. Опять же, я бы не занимался этим, если бы оно того не стоило.
Микросервисы решают как технические проблемы, так и проблемы людей
Чтобы понять, почему я уничтожаю микросервисы, давайте сначала разберемся, почему вообще они появились. Микросервисы решают два типа проблем: технические и человеческие.
В технической части некий аспект приложения оказывает чрезмерную нагрузку на инфраструктуру, что, в свою очередь, вредит UX. Например, обработка изображений потребляет массу процессорных мощностей. Из-за слишком высокой загрузки CPU остальные части приложения могут оказаться на «голодном пайке». В результате в системе могут возрасти задержки. И в самом худшем сценарии это способно повлиять на ее доступность.
С другой стороны, проблемы людей почти не имеют отношения к приложению и связаны с тем, как организована команда. Чем больше специалистов работают над некой частью приложения, тем более медленным и подверженным ошибкам становится процесс разработки. Например, стремление трех десятков инженеров провести непрерывное развертывание (CD) одного и того же сервиса приведет к образованию очереди. То есть вместо того, чтобы работать, большинство инженеров будут сидеть без дела в ожидании своей очереди на деплой.
Первые микросервисы в InVision решали преимущественно проблемы людей
В самом начале, 8 лет назад, InVision была монолитной системой, над которой работало всего 3 инженера. По мере роста и развития компании число систем почти не менялось, но размер команды начал быстро увеличиваться. Всего за несколько лет в компании появились десятки новых инженеров — как бэкенда, так и фронтенда. И все они работали над одной и той же кодовой базой, деплоили в рамках одной и той же очереди обслуживания.
Как упоминалось выше, проблемы начинаются, когда множество людей работают в одном месте. В результате разные команды конкурируют за одни и те же ресурсы для деплоя, при этом после каждого инцидента приходится откатывать код сразу нескольких команд и ни одна команда не могла деплоить, пока мы разбирались с инцидентом. Как вы понимаете, это создавало массу проблем по всей организации как для инженерной, так и для продуктовой команд.
Как итог, для решения «человеческой» проблемы и были внедрены микросервисы. Избранная группа инженеров начала разбивать приложения на части, которые, по их мнению, соответствовали границам ответственности команд. Это было сделано для того, чтобы команды могли работать более независимо, деплоить независимо и повысить свою продуктивность. Первые микросервисы в InVision почти никакого отношения не имели к решению технических проблем.
Закон Конвея хорош, если хороши границы
Работая с микросервисами, вы наверняка слышали о законе Конвея, сформулированном Мелвином Конвеем в 1967 году. Он гласит:
Любая организация, которая разрабатывает систему (в широком смысле), вынуждена создавать проекты, структуры которых являются копией структуры связей организации.
Этот закон часто иллюстрируется примером с компилятором:
Если четыре команды работают над компилятором, то на выходе вы получите четырехпроходной компилятор.
Идея здесь заключается в том, что решение «оптимизировано» с учетом командных структур (и командной коммуникации) и не обязательно предназначено для решения каких-либо конкретных технических или эксплуатационных проблем.
В предмикросервисном мире закон Конвея обычно рассматривался в негативном свете. Подразумевалось, что он намекает на плохое планирование и организацию приложения. Но в постмикросервисном мире толкование закона Конвея значительно расширилось. Потому что, как оказалось, если разбить систему на набор независимых сервисов с согласованными границами, то можно выпускать больше кода с меньшим числом багов. Связано это с тем, что команды теперь могут сильнее фокусироваться на неком наборе сервисов и результирующем более узком наборе обязанностей.
Конечно, преимущества закона Конвея сильно зависят от того, как провести границы и как они эволюционируют со временем. И вот тут я и моя команда, Rainbow Team, вступаем в игру.
В течение всех этих лет InVision приходилось эволюционировать как с точки зрения организации, так и инфраструктуры. Это означает, что под капотом скрыта как «старая» legacy-платформа, так и растущая «современная». По мере миграции команд на современную платформу сервисы, за которые отвечали эти команды, приходится передавать остающимся legacy-командам.
Сегодня — в 2020-м — моя команда выступает legacy-командой. Число сервисов, за которые она отвечает, медленно, но верно растет. И это означает: меньше людей, но больше репозиториев, языков программирования, баз данных, панелей мониторинга, журналов ошибок и бессонных ночей.
Короче говоря, все преимущества закона Конвея для организации со временем превратились в обязательства для моей legacy-команды. И поэтому мы пытаемся привести в норму нашу сферу ответственности, вернув баланс в закон Конвея. Другими словами, мы меняем границы сервисов так, чтобы они совпали с границей зоны ответственности нашей команды. А именно, мы возвращаем их в монолит.
Микросервисы — это не «микро». У них «правильный размер»
Пожалуй, худшее, что случилось с микросервисной архитектурой — это термин «микро», которым ее наградили. «Микро» — бессмысленный, но сильно нагруженный термин, пропитанный историческими коннотациями и человеческими предубеждениями. Гораздо более правильным был бы термин «правильный размер» (right sized). Микросервисы никогда не задумывались как «маленькие»; на самом деле подразумевалось, что они имеют адекватный, «правильный» размер.
Приставка «микро» ни к чему не относится; она ничего не означает, не влечет за собой никаких последствий. С другой стороны, «правильный размер» указывает на то, что сервис был разработан так, чтобы удовлетворять требованиям, предъявляемым к нему. То есть он отвечает за «правильный» объем функциональности. И эта «правильность» не отлита в металле — она зависит от команды, ее навыков, состояния организации, расчетной рентабельности инвестиций, стоимости владения и момента времени, когда этот сервис работает.
Для моей команды «правильный» размер означает меньшее число репозиториев, меньшие очереди на деплой, меньшее количество языков и панелей мониторинга. В случае моей сравнительно небольшой команды «правильный» размер скорее имеет отношение к человеческому фактору, нежели к технологиям. Другими словами, точно так, как InVision изначально внедряла микросервисы для решения «человеческой» проблемы, сегодня мы их уничтожаем для решений той же самой проблемы.
Цель — одна, пути ее достижения — кардинально отличаются.
И я очень горжусь своей командой и нашими усилиями по обслуживанию legacy-платформы. Наш отряд невелик, но его достижения с использованием имеющихся ресурсов заслуживают уважения. Подобный успех я приписываю глубокому знанию устройства legacy-платформы, агрессивному прагматизму и постоянным усилиям, направленным на разработку системы, которая соответствует нашим возможностям (вместо того, чтобы пытаться «раздуть» возможности до уровня существующей системы). Этот подход может показаться ограниченным, но он единственный подходит нам с учетом ресурсов, которыми мы располагаем в настоящее время.
Эпилог: большинству технологий не требуется «независимое масштабирование»
Независимое масштабирование часто приводится как аргумент в пользу создания независимых сервисов. Предполагается, что вы сможете более рационально использовать серверные мощности и базы данных. Другими словами, вместо того, чтобы масштабировать глобальный сервис целиком, столкнувшись с недостатком производительности в одной из его частей, вы можете независимо масштабировать только те микросервисы, которым это необходимо.
Из всех аргументов в пользу независимых сервисов этот встречается наиболее часто, но по моему (весьма ограниченному) мнению, обычно он не актуален. Заботиться о независимой масштабируемости, пожалуй, имеет смысл только в том случае, если некая часть функциональности привязана к процессору, памяти или вводу/выводу. Большую часть времени серверы пребывают в ожидании работы; добавление новых «обработчиков HTTP-маршрутов» в приложение вряд ли приведет к внезапному исчерпанию всех ресурсов.
Если бы я мог вернуться в момент, когда мы проводили разбивку на микросервисы, я бы наверняка начал со всей «завязанной на процессор» деятельности: обработки и изменения размера изображений, генерации миниатюр, экспорту/импорту PDF, управления версиями файлов с rdiff
, генерации zip-архивов. Я бы разбил команды с учетом этих границ и заставил бы сделать «чистые» сервисы, которые бы имели дело только со входами и выходами (другими словами, никаких «интеграционных баз данных», никаких «общих файловых систем»), чтобы все остальные сервисы могли их использовать, сохраняя слабую связанность.
Я не говорю, что это решило бы все наши проблемы — в конце концов, они были больше «человеческими», нежели «технологическими». Но это бы решило некоторую часть «правильных» проблем и облегчило бы нам жизнь в долгосрочной перспективе.
Эпилог: у микросервисов также есть вполне ощутимая финансовая сторона
Сервисы не функционируют в вакууме: они работают на серверах, посылают запросы в базы данных, экспортируют метрики и генерируют логи. Все это имеет вполне реальную стоимость. Лямбда-функция ничего не стоит, когда вы ее не используете, однако микросервисы, безусловно, стоят. Особенно если учитывать избыточность, которую приходится поддерживать для создания высокодоступной системы.
Усилия моей команды по возвращению микросервисов в монолит благоприятно сказались на расходах компании. Конечно, нельзя сказать, что вклад огромен: ведь речь идет всего лишь о нескольких небольших сервисах, — но он явно не нулевой. Таким образом, в дополнение к «человеческим» преимуществам от объединения систем, мы получаем еще и финансовую выгоду.
P.S. от переводчика
Читайте также в нашем блоге:
-
«Микросервисы: размер имеет значение, даже если у вас Kubernetes» (обзор доклада и видео);
-
«Предметно-ориентированная микросервисная архитектура от Uber».
Автор: Максим