Разбиваем монолит на микросервисы
В настоящей статье я предлагаю обсудить какие возникают ошибки при разбивке монолита на микросервисную архитектуру (МСА), почему они возникают, к чему приводят. Ну а в конце я опишу как должен быть организован эффективный и правильный процесс перевода на МСА и какой должна стать архитектура микросервисной системы.
Итак, ваша организация решила разбить старый добрый монолит на микросервисы. Почему? Ясного ответа никто дать, как правило, не может, но в целом все начинают описывать как им плохо живется с монолитом. Да, релизные циклы действительно очень зацеплены за разные команды. А почему вы думаете, что в МСА по-другому? Кто-то говорит, что микросервисы гораздо лучше масштабируются. Ну, можно сделать и так, а вам зачем это? Нет, может и надо, но вы понимаете зачем или просто подсмотренную фразу используете? Говорят, каждый микросервис гораздо менее требователен к ресурсам: памяти, базе данных и т. д. Ну и что? У вас деньги на сервера иссякли? Бизнес-ценность-то в чем?
Коллеги, я не хочу сказать, что у МСА нет преимуществ. Эти преимущества есть. Но я хочу сказать, что какие бы цели вы ни ставили при старте проекта разбивки, вы их скорее всего ставите неправильно и никогда не достигните. Не достигните просто потому, что реализацией проекта у вас будут заниматься те люди, которые довели до состояния бездарно написанного кода ваш монолитный проект. При этом все подходы при реализации МСА настолько отличаются от монолитной, насколько телефонная лапша 20-го века отличается от сетевых технологий нынешнего 21-го века. И аналогия здесь действительно очень удачная. ТФоП доставляет в квартиру одну телефонную линию. Обрыв на любом участке линии приводит к выходу ее из строя. Сетевые технологии динамичны и позволяют строить альтернативные маршруты. Даже выход из строя 60 % всей сетевой инфраструктуры страны в результате ядерной войны, не приведет к отказу оставшихся сетей.
Т. е., главное преимущество МСА перед монолитом — это динамичность, которая способна приводить к чрезвычайной надежности системы. Тут надо пояснить: из самой МСА никак не следует, что она будет надежна. МСА лишь дает вам возможность строить надежные системы. Но это ваша ответственность заложить в архитектуру вашей системы надежность и дублирование функционала.
А сейчас разберем повсеместно встречающиеся ошибки при развитии микросервисной системы предприятия.
Отказ от изменений бизнес-процессов
Говорят, что любой бизнес реализует в коде свои бизнес-процессы. И, если вы 20 лет до этого строили свои бизнес-процессы на базе вашей монолитной архитектуры, то любая ваша попытка внедрить МСА будет заведомо обречена на провал. Просто потому, что для этого требуется менять бизнес-процессы. Пример? Сколько стадий согласования вопроса у вас существует в организации? Так вот, в микросервисной команде число таких стадий приближается к нулю. Подавляющее большинство вопросов решается внутри команды, реализующей микросервис. Команда не обязана выносить на корпоративный уровень вопросы о языке, на котором будет написан микросервис.
Одни могут выбрать Java, а другие — Python. Вы может быть даже сейчас не поверите, но этот вопрос является полностью в компетенции команды. И это потому, что в случае каких-то проблем микросервис проще ПЕРЕПИСАТЬ, чем ПОДДЕРЖИВАТЬ.
По моему опыту, разработка простейшего микросервиса при нормально поставленном производстве занимает неделю работы двух джунов, включая бюрократию по выводу его в пром, т. е. обходится компании, включая различные накладные расходы, примерно в 50-100 тыс. руб. Если у вас только аналитика занимает месяц работы 3 команд, то у вас нет никакой МСА в организации, вы опять скатываетесь в лютую монолитчину.
Поручить руководство проектам опытным монолитчикам
После того как вы отказались от модернизации своих бизнес-процессов, совершенно логичным является то, что вы поручаете новый проект очень опытному человеку, который показал себя с лучшей стороны и вообще знает все ваши бизнес-процессы. Возможно кто-то вам и нудел, что на старые проблемы должен взглянуть новый опытный человек, но вы отмахнулись от него как от глупой назойливой мухи. И вот он. Ваш новый/старый руководитель разработки на проекте. Не удивляйтесь, что результат будет тем же, что и раньше, и даже хуже. Когда в МСА начинают применяться монолитные решения, ни к чему хорошему это не приведет. Именно в этот самый момент вы подписали смертный приговор вашему пилоту. Возможно, вы даже наберете опытных людей, которые уже сожрали стаю собак на микросервисных проектах, но это вас не спасет, просто потому что их начальник слушать не будет. Просто потому что у него мозги не заточены под МСА, а советы других он будет воспринимать как чудовищную глупость.
Архитектура разрабатывается архитекторами без опыта разработки
Вот сидит такой архитектор, который за свою жизнь не написал ни строчки кода, и выдает распоряжения разработчикам. Очень часто разработчики оказываются более квалифицированными, чем он сам, но он, как наполеончик, отдает распоряжения. Распоряжения, конечно же, глупые. Примеры этих распоряжений смотрите дальше.
Повторить функционал монолитной системы
Ну, это же логично: надо сначала полностью воспроизвести то, что уже есть, а потом двигаться дальше. Воспроизвести все баги и костыли, все то дерьмо, от которого годами плюются разработчики.
Мне одно не понятно: с чего эти архитекторы взяли, что потом кто-то даст денег на рефакторинг? Т. е. вы копируете вашу морально устаревшую систему, не привносите ничего положительного с точки зрения функционала и с этим 20 летним старьем вы будете жить еще как минимум 10 лет до следующего рефакторинга.
Переиспользование кода
Любой монолитчик знает, что код надо переиспользовать. Если сделал функцию User::toString, то в рамках МСА ее сейчас нужно выделить в отдельный микросервис и все 1000 других микросервисов будут ломиться к ней для сериализации каждого юзера. То, что первый же сбой в микросервисе положит всю систему, — в монолитах же такого не было.
Впервые с боевой микросервисной архитектурой я столкнулся в 2017 году. К тому времени система уже работала 7 лет, и за это время произошла полная смена команды. Сотни микросервисов. Документации никакой нет. Нет даже простого описания назначения каждого микросервиса. И вообще не понятен статус микросервиса: функционирует, деактивирован, экспериментальный и пр. В случае возникновения проблемы, трассировка микросервисов превращалась в сплошной кошмар. В итоге в команде просто никто долго не держался. Текучка стала бичом команды. За 3 месяца команда могла просто обновиться полностью.
Это реальная история неудачно спроектированной микросервисной системы. Такой финал ждет подавляющее большинство пилотов, которые сейчас стартовали. А все из-за ошибок, которые я перечислил выше.
А сейчас я хочу рассказать, как надо разрабатывать микросервисную систему:
- Проанализируйте свой предыдущий опыт, составьте список того, что считаете удачным, а что вам следует пересмотреть. Проведите опрос клиентов, пускай они запросят необходимые изменения в функционале. Ваша цель — путем одного мелкого и ювелирно точного рефакторинга достичь нескольких бизнесовых целей. Ваша цель — не переписывать одно и то же 10 раз, а создать бизнес-продукт, который будет приносить деньги. Вы не просто должны сделать копию легаси-системы, а должны построить новейшую систему, которая выведет вас на передовой край ИТ-отрасли. Зачем вам эти старые костыли?
- Пересмотрите свои бизнес-процессы. Если у вас любой agile всегда скатывается к жесткому водопаду, если согласования и аналитика занимают месяцы, то ваше производство ПО требует кардинальной модернизации. А для этого нужно...
- …найти специалиста с большим опытом разработки микросервисных систем. Пускай он не посвящен в ваши бизнес-процессы, но этот новый человек посмотрит на ваши застарелые проблемы свежим взглядом и даст действительно ценные рекомендации. Кроме того, только человек с реальным опытом микросервисной разработки способен предусмотреть те подводные камни, которые вам встретятся. Ваш опытный монолитчик только все запорет.
- Легаси-разработчики — это ваш резерв, который в новой разработке сможет выступить ценным экспертным звеном. Но люди, которые пилили монолит в виде костылей, ни в коем случае не должны стать костяком разработки микросервисной системы и определять ее архитектуру. Монолитчиков должна ждать стажировка под руководством людей с опытом построения микросервисных систем. И главное, что ждет монолитчиков, — это жесткий слом мозга и полная перестройка мышления.
- Каждый микросервис — это не просто мелкая функция бэкенда. Это полный цикл разработки бизнес-функции. Одна команда полностью должна нести ответственность за всю разработку этой бизнес-функции как на фронтенде, так и в базе данных. Как только вы начинаете делегировать часть разработки другим командам, вы тут же начинаете погрязать в интеграциях. Интеграции в МСА — это еще более дорого, ненадежно и неэффективно, чем в монолите. Необходимо снижать их количество. В качестве микросервиса вполне нормально выбрать CRUD для какой-то сущности, например, сущности клиентского договора. Это нормально, если команда предоставит как бэкенд, так и фронтенд-микросервис (или библиотеку) для работы с договорами: список, создать, обновить, удалить. Главное — это чтоб команда несла полную ответственность за то, как эта функция будет работать на сайте и в мобилах.
- Не нужно заниматься фанатизмом при внедрении микросервисной архитектуры. При правильной микроархитектуре сервисов вы сами решаете, в какой форме выпустить приложение: в монолитной, микросервисной или бессерверной архитектуре. Ожидайте, что ваша бизнес-постановка может измениться в любой момент, и вы должны с легкостью реализовать изменения. Гибкая разработка — это то, что просто без лишней болтовни должно реально применяться на всех уровнях.
- С недоверием относитесь к переиспользованию функционала. Наоборот, любой функционал должен дублироваться. Ваш выигрыш 10 гигабайт дисковой памяти никого не впечатлит, если справочник, который используют 30 микросервисов, будет остановлен из-за сбоя, приведя к каскадному отключению всей микросервисной системы. Микросервисы должны КУПИРОВАТЬ сбои сторонних сервисов, а не усиливать их. И этот принцип — это главная проблема для монолитчиков. После 20 лет работы с реляционными БД, после десятилетий опыта нормализации таблиц и структур данных в приложениях, очень сложно приучить себя к мысли, что дублирование, репликация, шардирование, денормализация — это нормально и полезно для проекта, а переиспользование и нормализация — это потенциально сбойные места, готовые положить всю систему.
- И вообще, что произойдет после сбоя одного из модулей? Вы просто должны моделировать все такие сбои и штатно обрабатывать их. Каскадное отключение всей системы — это лишь один из сценариев. Неприятностей может быть много. Это в монолите все компоненты находятся в одном Jar-нике. В МСА каждый микросервис отделен ненадежными и компрометируемыми сетевыми коммуникациями. Это не плохо и не страшно. Это надо просто держать в голове при разработке и предусматривать сценарии разрыва этих коммуникаций.
- Если вы очень любите Spring, Hibernate и OracleDB, то, скорее всего, вы никогда не сможете построить надежную и быструю микросервисную систему. Spring был изобретен в годы становления монолитной архитектуры. Это огромный монстр, который даже в функции простого Hello World превратится в jar-файл размером в сотни мегабайт. Просто старт такого приложения растягивается на минуты. И эти гигабайты бессмысленного цифрового мусора будут пожирать ваши серверные ресурсы 24x7x365. Oracle, Postgres, MySQL — это все жуткое старье, которое было построено из расчета, что база данных должна крутиться на одном сервере. Да, время идет и все эти базы данных обзавелись средствами масштабирования, но до сих пор они в этом вопросе совершенно неуклюжи и ненадежны. Существуют целые классы баз данных (NoSQL, NewSQL), которые создавались в парадигме Big Data, High Availability, распределенное хранение и т. д. И эти ораклы с постгресами с ними просто не способны конкурировать по надежности и скорости работы. Все эти “крутые” спринги, ораклы и хайбернейты — это наследие уходящей эпохи монолита. Эпоха микросервисов и облачных функций — это быстрый старт приложений при возникновении нагрузки, отсутствие состояний для высокой масштабируемости и безжалостная выгрузка всех приложений и ресурсов, которые в данный момент не нужны и лишь бессмысленно расходуют оперативную память.
Заключение
В заключение хочу еще раз отметить, что я ни в коем случае не против разбиения монолитных систем на микросервисы. Напротив, я считаю, что такой подход может привести к значительно большей устойчивости вашей ИТ-инфраструктуры. Бездумное внедрение элементов микросервисной архитектуры без понимания общей теории построения подобных систем, полное игнорирование практики отрасли и вообще здравого смысла — вот что отправляет ваши пилоты на свалку истории. Только ошибки людей вашей организации приносят слезы и убытки ваших инвесторов.
Напротив, разумный подход может действительно ускорить ваши сервисы и сделать их чрезвычайно устойчивыми. Поэтому, очень хочу пожелать мудрости всем, кто занимается развитием ИТ в компаниях.