Как уменьшить сложности реализации микросервисных систем при проектировании и учесть ожидания всех сторон?
Монолит или микросервисы? Как ИТ-сообщество в целом, так и отдельные компании, команды и заказчики пытаются найти ответ на вопрос, какой из подходов выбрать для очередного проекта. В зависимости от уровня и характера решаемых задач аргументы за и против приводятся с учетом времени вывода на рынок (time to market), расходов на разработку, удобства поддержки, требований к отказоустойчивости, производительности, масштабируемости и прочего.
Увы, каждый раз, если с проектом что-то пошло не так, звучит один и тот же вопрос: «Может быть имело смысл использовать монолит/микросервисы (нужное подчеркнуть)?» В итоге обсуждения уходят на очередной круг – часто с теми же аргументами и вновь приобретенным «болезненным» опытом применения того или иного подхода.
Мы в SimbirSoft тоже сталкивается с такими же вопросами, проблемами, накапливаем опыт применения монолитов и микросервисов. Все рассуждения будем вести, глядя на ситуацию из микросервисного и облачного мира, выстраивая параллели с тем, как похожие задачи решаются монолитами.
Эта статья – своего рода ретроспектива на тему разработки микросервисов и связанных с этим сложностей, прежде всего на этапе анализа и проектирования. Мы сделали акцент именно на этих этапах, поскольку принимаемые в рамках них решения имеют основополагающее значение.
Как найти баланс между ожиданиями пользователей, заказчика и возможностями архитектуры
Если упростить, то любой проект – это в первую очередь набор пожеланий и ожиданий бизнеса, будущего владельца продукта. Готовый ИТ-продукт с точки зрения его заказчика – набор решений, который автоматизирует бизнес, позволяет увеличить доходы и максимально удовлетворить конечных пользователей. И соответственно то, как ведет себя продукт после релиза, с точки зрения пользователя будет олицетворять заказчика. В свою очередь, ожидания пользователей и заказчиков влияют на то, какому архитектурному стилю будет отдано предпочтение.
Что важно пользователю
Если рассматривать ситуацию с точки зрения конечного пользователя (а именно от его лояльности в большинстве случаев зависит будущее разрабатываемых приложений), то важными факторами, помимо работоспособности всех ожидаемых бизнес-функций, являются следующие нефункциональные требования:
- Производительность
Видение пользователя: страницы загружаются быстро, время ожидания минимально.
Здесь важны размер приложения, число пользователей, количество ожидаемых запросов в секунду, т. е. степень нагруженности. Если приложение небольшое, выполняет ограниченный набор функций, не является нагруженным и по его дальнейшему масштабированию нет четких планов, достаточно использовать монолитную архитектуру. Дробление на микросервисы в угоду красоте подхода и эфемерным перспективам роста на будущее чревато усложнением архитектуры, появлением сетевых взаимодействий и проявлениями прочих недостатков микросервисов там, где этого можно было бы избежать.
Если планируемый размер приложения достаточно велик, то микросервисный подход дает больше пространства для маневра в контексте повышения производительности, в первую очередь обеспечивает гибкое горизонтальное масштабирование и балансировку. При этом компоненты системы взаимодействуют не в рамках одного сервера, а по сети, что сказывается на производительности в негативную сторону. Снизить эти риски позволяет корректная работа с нефункциональными требованиями и подход Design API First – прежде всего за счет выявления картины взаимодействий на ранних этапах и формирования технических концепций обмена данными.
Здесь крайне важна тесная совместная работа аналитика, архитектора и заказчика, в ходе которой можно не только разобрать текущие требования, но и сделать предположения о дальнейшем наиболее вероятном векторе эволюции системы.
- Отказоустойчивость
Видение пользователя: с одной стороны, это возможность в любое время работать с приложением, не наблюдая вместо этого страницу технических работ. С другой стороны, допустим частичный отказ, при котором часть функций недоступны, но в целом с приложением можно продолжать работать.
Отказоустойчивость – один из первых аргументов к использованию микросервисов. Они позволяют вводить необходимую избыточность (например, иметь резервные экземпляры сервисов на случай отказов), реализовывать feature toggling на случай частичного отказа. Сложность кроется в определении узких мест. Не менее важно своевременно обнаружить вышедший из строя микросервис, что накладывает дополнительные требования к мониторингу.
Большой монолит выглядит довольно неповоротливым, однако микросервисы несут дополнительные затраты. Выявление узких мест и продвинутый мониторинг, в особенности с использованием искусственного интеллекта, позволяет определить наиболее подверженные отказам сегменты архитектуры и принять меры. В монолитной архитектуре также возможна реализация feature toggling и работа с частичными отказами (например в архитектуре, основанной на плагинах), однако при определенном размере монолит будет нарушать требование оперативной техподдержки.
При анализе ожиданий пользователей совместно с заказчиком лучше сразу прояснить требуемый уровень отказоустойчивости. Может оказаться, что узких мест не так много, они не столь критичны, и сам уровень отказоустойчивости получится существенно снизить. Как следствие, появится возможность использовать гибридный архитектурный стиль.
- Оперативная техподдержка и доступность
Видение пользователя: если приложение работает не так, как ожидается, это должно быть максимально быстро исправлено.
От монолитов среднего и крупного размера крайне сложно добиться необходимых SLA-метрик по возвращению приложения в строй. Однако некоторые семейства решений данной проблемы в монолитной архитектуре также имеются (к примеру, blue-green deploy).
С микросервисами также есть свои сложности. Обеспечение дублирования влечет за собой ввод в экосистему дополнительных узлов с балансировщиками нагрузок, реализацию синхронизации данных, механизмов распределенного кеширования и прочее. Решения этих проблем известны. Вопрос лишь в том, на какие дополнительные затраты готов пойти заказчик ради достижения поставленных условий.
Крайне важно на этапе обсуждения требований и набросков концепции системы прозрачно обозначить заказчику подобные риски и предложить альтернативные решения.
В случае небольших приложений монолит может быть вполне приемлемым, поскольку время повторного развертывания приложения не так велико. В некоторых случаях, например, при специфической аудитории пользователей (сотрудники производственного цеха, которые пользуются системой в фиксированные моменты времени, или школьники, использующие приложение строго в учебное время), нахождение системы в офлайн-состоянии допустимо и может выполняться согласно прогнозируемому графику.
- Безопасность
Видение пользователя: персональные данные должны быть надежно защищены
В случае монолитного и микросервисного подхода есть множество проверенных механизмов обеспечения безопасности приложений. Отличие состоит в том, что при использовании микросервисной архитектуры риску могут быть подвержены не все данные одновременно. Например, если атаке подвергся отдельный сервис с ограниченным доступом, то остальная инфраструктура не пострадает. При использовании облачного подхода часть задач по обеспечению безопасности берет на себя оператор, что является несомненным плюсом, но увеличивает расходы на содержание системы. Также при использовании микросервисов снова выходит на первый план задача мониторинга с целью своевременного обнаружения аномального поведения и принятия контрмер.
Еще одно следствие реализации высоких требований к безопасности – потенциальное увеличение накладных расходов на различные операции. Это также требует анализа с участием систем мониторинга и может повлечь перепроектирование отдельных сегментов системы. В этом отношении рекомендуем не пренебрегать требованиями к безопасности на старте, несмотря на кажущееся низкое влияние на ключевые бизнес-функции системы. Даже отложив реализацию security-части системы на более поздние этапы, при разработке системы этот аспект стоит всегда держать во внимании.
При обсуждении требований к безопасности важно как можно раньше выделить наиболее критичные для бизнеса и чувствительные категории данных. Также возможен вариант, когда заказчик уже обладает инфраструктурой, в которую можно встроить разрабатываемое решение, избежав перепроектирования с нуля. Речь идет о таких системах, как OpenId, LDAP и прочих security-механизмах, которые можно развернуть у заказчика.
Что важно заказчику
Приведенный выше список требований важно дополнить пожеланиями самого заказчика, который выступает поставщиком продукта для конечных пользователей. Здесь, помимо удовлетворения запросов пользователей, в игру вступают следующие интересы:
- Минимизация расходов: стоимости разработки, поддержки и time to market
Один из наиболее критичных показателей для большинства заказчиков. И здесь дилемма «монолит-микросервис» стоит довольно остро. С одной стороны, монолит выглядит дешевле: одно приложение, один экземпляр базы данных, один стек технологий, одна кодовая база, никаких сетевых взаимодействий внутри backend-части и прочее. Казалось бы, выбор в пользу монолита очевиден, зачастую именно он и делается. Это справедливо для проектов небольшого размера.
Когда же мы имеем дело с крупными системами, даже внутри разрастающегося монолита решает принцип «разделяй и властвуй». Рано или поздно система приходит к необходимости разделения монолита на группы отдельных приложений. Чтобы в перспективе не тратить на это ресурсы, особенно когда очевидна тенденция к росту размера приложения, принимается решение о закладывании микросервисной архитектуры на старте.
Но тут есть риск затянутого выпуска минимальной работоспособной версии (MVP) системы из-за высоких накладных расходов, а именно: разработки и развертывания сопутствующих систем, напрямую не реализующих бизнес-функции (балансировщиков, систем кеширования, обнаружения, API Gateway и т.п.). На этом этапе команде крайне важно корректно выстроить диалог с заказчиком, убедить его в необходимости предпринимаемых шагов и, что немаловажно, постараться регулярно демонстрировать реализованные фрагменты системы.
При работе с требованиями заказчика, как и при формировании требований, имеет смысл несколько раз подумать о требованиях к отказоустойчивости и доступности. Часто попытка добиться «максимума девяток» (доступность 99.999…) приводит к неоправданно высоким затратам не только на старте, но и на всех последующих этапах разработки.
Также с заказчиком необходимо обязательно обсудить ожидаемую динамику развития системы с точки зрения повышения расходов на облачные сервисы. Если этот момент упущен из внимания как некий фоновый и казалось бы очевидный для команды разработки, он может стать неприятным сюрпризом для заказчика. Как следствие, нехватка ресурсов ударит и по самой команде, вынуждая искать обходные пути, чтобы обеспечить производительность в отсутствие возможности наращивания аппаратных ресурсов.
- Поддержка репутации своего бренда
Важнейший показатель, который нередко рассматривается с менее высоким приоритетом по сравнению с техническими аспектами. Решение клиента об использовании микросервисной архитектуры или определенного стека технологий в ряде случаев может быть продиктовано желанием создать образ передовой, инновационной компании. Ради этой цели некоторые заказчики готовы нести дополнительные затраты, в том числе и на микросервисы.
Задача архитектора и аналитика состоит в том, чтобы по возможности минимизировать противоречия между репутационными и техническими требованиями.
В частности, если из репутационных соображений требуется реализация микросервисного приложения, но при этом само приложение небольшое, то один из вариантов – заложить небольшой сервис-монолит с парой так называемых микросервисов-сателлитов на периферии для выполнения небольших частных задач. С концептуальной точки зрения подобное приложение уже становится распределенным, но еще не требует повышенных накладных расходов как в случае, если бы оно было микросервисным по всем правилам.
- Работа в знакомой среде
При проектировании приложений, в особенности микросервисных, важно не забывать о законе Конвея, когда «организации проектируют системы, которые копируют структуру коммуникаций в этой организации». Нередко на этапе согласования структуры приложения заказчик может неосознанно стремиться повторить структуру своего предприятия. При этом в действительности, какой эффективной бы она ни была, при переносе в информационную систему будет работать по другим принципам, а значит может значительно потерять свою эффективность.
Архитектору и аналитику обязательно стоит иметь в виду эту особенность и грамотно направлять заказчика, информируя об этих различиях.
Выводы
При проектировании любой информационной системы необходимо учитывать множество факторов, в частности пожелания заказчика и конечного пользователя, технические аспекты, которые напрямую влияют на дальнейшую работоспособность, и прочее. И у монолитной, и у микросервисной архитектуры есть свои технологические ниши и набор условий применимости, в рамках которых можно получить максимальную выгоду от каждого подходов и минимизировать недостатки. Важен технологический баланс с поправкой на приоритеты бизнеса.
Ключевым фактором при проектировании сложных IT-систем, в том числе микросервисных, является наличие множества одновременно действующих факторов и необходимость постоянной коммуникации с заказчиком. Коммуникации часто выходят на первый план, что требует от архитектора и аналитика не только учитывать технические последствия, но и доступно разъяснять заказчику особенности тех или иных решений.
В ходе разработки микросервисных проектов в наибольшей степени проявляется требование к прозрачности процессов. Сегодня это одна из наиболее высокоуровневых технологий. Но при всех видимых преимуществах несет множество неявных накладных расходов – как в момент разработки, так и в перспективе. Только ясное понимание этих особенностей всеми сторонами позволит бизнесу эффективно внедрять подобные решения или вовремя отказываться от них, если количество аргументов против в конкретном случае окажется больше.
Опубликовано 17.04.2024