Корпоративные бизнес-приложения нельзя считать образцом для подражания: сложный пользовательский интерфейс, перегруженный формами ввода, запутанными меню и иерархическими списками; многошаговые операции, ни на одном этапе которых нельзя ошибиться; наличие большого числа ограничений и долгие сроки внесения изменений — все это резко контрастирует с сервисами, предоставляемыми во Всемирной паутине, социальных сетях и мобильных приложениях. Но особенно удручает корпоративных пользователей низкий уровень доступности бизнес-приложений — плановые работы, не позволяющие воспользоваться системой, или непредвиденные сбои случаются именно в тот момент, когда необходимо выполнить срочную работу. ИТ-отделы организаций стараются изменить ситуацию: внедряют новые приложения, сокращают сроки доработки существующих систем, постоянно повышают уровень их доступности на очередную долю процента. Однако похоже, что даже сами ИТ-отделы уже не верят в позитивный результат этой многолетней борьбы.

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

Несмотря на то что до сих пор нет четкого определения микросервисов, известен набор характеристик, помогающих идентифицировать этот архитектурный стиль. По сути, микросервисная архитектура — это метод создания распределенных приложений в виде набора независимо разрабатываемых и развертываемых небольших сервисов, запускаемых как один или несколько изолированных процессов. Все это очень похоже на давно известную сервисную архитектуру (Service-Oriented Architecture, SOA), которая решает ту же задачу — снижение сложности ИТ-ландшафта. Иногда утверждается, что микросервисы — это и есть правильно реализованная SOA, однако следует обратить внимание на ряд ключевых различий между этими подходами.

Во-первых, в качестве программных интерфейсов для взаимодействия с микросервисами, как правило, используют RESTful API и асинхронный обмен сообщениями через очереди (рис. 1), а для реализации сервисной архитектуры использовался протокол SOAP. Строго говоря, SOA не определяла способ взаимодействия между сервисами, но на момент ее появления какой-либо реальной альтернативы использованию SOAP не было. Из-за этого сервисы и микросервисы различаются по логической организации. Микросервисы реализуют возможность управления структурированным информационным ресурсом посредством ограниченного набора операций: чтения и обновления его отдельных частей. А все взаимодействия строятся без сохранения на сервере состояния клиента. Cервисы в SOA не используют концепцию ресурса, а представляют собой набор операций над некоторыми объектами, которые четко нигде не определены. По сути, SOA-сервис — это набор из множества методов, выражаемых глаголами инициации операций по созданию или модификации таких объектов.

Рис. 1. Программные интерфейсы микросервиса
Рис. 1. Программные интерфейсы микросервиса

 

Во-вторых, множество SOA-сервисов зачастую развертывались в одном процессе: сервере приложений, веб-сервере или сервисе интеграционной среды, — тогда как микросервисы принято развертывать в изолированном окружении (рис. 2). Например, при работе с открытым ПО пакет установки часто включает в себя не только само приложение, но и дистрибутивы системы управления базой данных, веб-сервера, другого необходимого ПО, а также уже настроенные файлы конфигурации. Установка и запуск всех необходимых компонентов полнофункционального решения производятся буквально одной командой. Неважно, запускается система в облаке или на локальном компьютере, — такой подход меняет жизненный цикл разработки и эксплуатации программных компонентов, обеспечивая независимость командам разработки в выборе инструмента и способа организации данных, с одной стороны, и стирая различия между средой разработки и средой эксплуатации, с другой.

Рис. 2. Разнообразие программных средств при использовании микросервисной архитектуры
Рис. 2. Разнообразие программных средств при использовании микросервисной архитектуры

 

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

Появление микросервисов в архитектуре информационных систем можно сравнить с переходом от функционального к объектно-ориентированному программированию. До середины 1990-х годов разработка представляла собой написание пакетов функций, которые потом вызывались из основного приложения. Было крайне важно выделить из разных частей программы схожие фрагменты бизнес-логики и реализовать их в единой библиотеке. С появлением объектно-ориентированного подхода все изменилось. Общий функционал реализуется в базовом классе в виде расширяемого набора данных и методов, которые можно в дальнейшем переопределить. Прикладной программист наследует свое приложение от готового класса, разрабатывая лишь небольшой объем нового кода для расширения некоторых методов. Точно так же и микросервис «переопределяет» небольшую часть функционала вызвавшего его приложения. В микросервисе реализуется то, что не реализовано в исходном приложении или реализовано не совсем так, как надо. Этот принцип формулируется как «начните с монолитного приложения» (Monolith First) и является одним из главных ключей к пониманию микросервисной архитектуры.

Микросервисы: смена архитектурной парадигмы?

Ряд характеристик микросервисов, таких как децентрализованный выбор стека технологий или независимая организация данных, дают основание считать, что микросервисы нарушают привычные правила «хорошей» корпоративной архитектуры. Архитекторы предприятий на протяжении многих лет методично прививали организации набор определенных принципов. Часть из них нашла свое отражение в политиках и руководствах. Другая существует в виде неформальных договоренностей и соглашений. Третья реализуется архитекторами в форме архитектурного надзора за проектами. Эти правила хорошо известны и воспринимаются как само собой разумеющееся: необходимо стремиться к унификации серверов приложений, СУБД и инструментов разработки, избавляться от нескольких версий одного и того же программного средства, консолидировать информацию и приводить структуры данных к единому формату.

Принципы микросервисной архитектуры выглядят отрицанием всех этих идей. Каждый микросервис включает в себя свой стек технологий, выбор которого осуществляется непосредственным разработчиком. Вместо единой базы данных в каждом микросервисе используется собственный инструмент хранения информации, причем выбор реляционной или нереляционной СУБД, способа организации данных, атрибутивного состава и программных интерфейсов для предоставления данных ни с кем не согласуется. Более того, сходные по своему характеру данные могут быть распределены по нескольким экземплярам микросервиса. Зачастую микросервис проще переписать заново, чем доработать, а добавление нового функционала в приложение предпочтительней реализовывать в виде нового микросервиса, а не посредством переработки уже существующего отлаженного кода.

Но так ли велики преимущества микросервисной архитектуры, чтобы разом отказаться от устоявшихся архитектурных принципов? Можно ли начать использовать микросервисы только в одном из корпоративных приложений, не затрагивая другие, а решение об их полезности принимать по результатам пилотного проекта? Да, именно так и следует выстраивать проект по внедрению микросервисов в корпоративный ИТ-ландшафт.

Микросервисы с точки зрения ИТ эксплуатации

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

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

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

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

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

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

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

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

Рис. 3. Один из вариантов архитектуры развертывания микросервисов
Рис. 3. Один из вариантов архитектуры развертывания микросервисов

 

Но как не потерять данные, которые успели накопиться в неудачном релизе? Общего ответа на этот вопрос нет, но есть несколько частных случаев, для которых эта задача легко решается. Один из распространенных шаблонов проектирования распределенных систем предписывает разделять запросы на чтение данных и команды на их модификацию (command-query responsibility segregation). Если микросервис был спроектирован в соответствии с этим принципом и обрабатывал только запросы на чтение, то новых данных от пользователей он еще не накопил, и после возврата маршрутизации запросов на предыдущую версию сервиса новую неудачную версию можно просто выключить. С обработкой команд задача немного сложнее. Тем не менее команды на изменение данных обычно не обрабатываются синхронно, а помещаются в очереди сообщений, что обеспечивает большую гибкость в организации логики обработки. Можно продублировать поток сообщений и сравнить результаты их обработки разными версиями сервиса, сохранить часть сообщений для последующей обработки проверенной версией, написать обработчики для отмены изменений и сделать многое другое.

Построение таких архитектур требует дополнительных усилий, но себя окупает. Задача архитектора всегда заключалась в  правильном разделении системы на компоненты — так, чтобы их можно было создавать, развивать и заменять независимо друг от друга, силами небольших специализированных команд, использующих наиболее подходящий для конкретной задачи набор технологии. Эта деятельность никогда не была простой. Невозможно предвидеть требования, которые будут сформулированы через год или два, строить прогнозы относительно успешности в будущем тех или иных технологий, разрабатывать структуры для пока еще не собранных данных. Однако еще одно свойство микросервисов — эволюционирующая архитектура — позволяет сделать и это. Речь идет об изначальном построении системы таким образом, чтобы в дальнейшем ее развитие заключалось не в переработке существующих модулей, а в присоединении к приложению новых компонентов и источников данных. Это чем-то напоминает архитектуру микроядра, используемую при разработке ОС. Микроядро реализует самое необходимое, а все прикладные функции в такой архитектуре выносятся во внешние модули. Только в случае операционных систем речь идет о драйверах устройств, функциях работы с файловыми системами и сетями. В микросервисной архитектуре во внешние подключаемые модули выносится прикладной функционал. Это свойство микросервисов часто называют «организацией сервисов вокруг бизнес-возможностей».

Но, пожалуй, самым востребованным результатом перехода к микросервисной архитектуре будет структурирование процесса разработки приложений, выстраивание его в виде параллельной деятельности независимых agile-команд разработчиков. Распределение задач между такими командами, разделение ответственности, организация взаимодействия между командами определяются в этом случае самой архитектурой микросервисного приложения.

Варианты использования

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

Проекты создания «единого окна», интегрирующего в общий пользовательский интерфейс функционал десятка разрозненных приложений, никогда не были простыми. В рамках таких проектов сложно обойтись без [I]обновления унаследованных приложений[$]. Существующие системы не были предназначены для интеграции — предполагалось, что с ними будут работать люди, поэтому о хороших программных интерфейсах со стороны таких приложений остается только мечтать. Если программные интерфейсы и существуют, то они плохо абстрагированы, несут на себе печать конкретной реализации, а ограничения унаследованных систем по уровню доступности, количеству одновременных обращений или актуальности данных делают невозможным их практическое использование. Рядом с такой системой приходится создавать онлайн-хранилище данных и конвейер обработки событий. Впрочем, подобные затраты не напрасны — они позволяют не только интегрировать такие системы в композитные ИТ-решения, предназначенные для клиентов или сотрудников, но и реализовывать новый функционал без внесения изменений в унаследованное приложение. Можно пользоваться уже имеющимися в системе функциями и данными, но реализовывать новые бизнес-процессы в отдельных изолированных от приложения микросервисах. Это более быстрая и экономически обоснованная альтернатива замене или полному переписыванию устаревших систем.

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

***

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

Максим Смирнов (mxsmirnov@gmail.com; mxsmirnov.com) — главный архитектор компании «Бинбанк Диджитал» (Москва).