Корпоративные бизнес-приложения нельзя считать образцом для подражания. Сложный пользовательский интерфейс, перегруженный формами ввода, запутанными меню и иерархическими списками, многошаговыми операции, ни на одном этапе которых нельзя ошибиться, наличие большого числа ограничений и долгие сроки внесения изменений – всё это резко контрастирует с сервисами, предоставляемыми нам в сети интернет, социальными сетями, мобильными приложениями.
Но особенно удручает корпоративных пользователей низкий уровень доступности бизнес-приложений. Плановые работы, не дающие возможность воспользоваться системой, или непредвиденные сбои случаются именно в тот момент, когда срочно необходимо выполнить важное и срочное дело: сформировать сложный заказ, оформить долгожданный договор, решить проблему крупного клиента. ИТ-отделы организаций стараются изменить ситуацию: внедряют новые приложения, сокращают сроки доработки существующих систем, постоянно повышают уровень их доступности на очередную долю процента. Но кажется, что даже сами ИТ-отделы уже не очень верят в позитивный результат этой многолетней борьбы.
Представьте, что: доступность бизнес-приложений можно было бы увеличить в несколько раз; в течении недели устанавливать десятки обновлений, не рискуя нарушить работоспособность корпоративной информационной системы; разрабатывать такие обновления параллельно силами нескольких команд, создающих новые релизы независимо друг от друга. В такие возможности сложно поверить. Если бы пару лет назад мне кто-то рассказал о существовании подхода, меняющего деятельность корпоративных ИТ таким образом, я бы, вероятно, решил, что у моего собеседника просто недостаточный опыт развития и эксплуатации информационных систем предприятия. Но сегодня уже можно уверенно сказать, что микросервисная архитектура – это именно такой подход. C каждым днем растет поток сообщений об успешном опыте использовании микросервисов в самых разных организациях. А описываемые преимущества микросервисной архитектуры для предприятий столь важны, что от этих сообщений уже нельзя просто так отмахнуться.
Что такое микросервисная архитектура
Несмотря на то, что нет четкого определения микросервисов, определен набор характеристик, которые помогают нам идентифицировать этот архитектурный стиль. По сути, микросервисная архитектура – это метод создания распределенных приложений в виде набора независимо разрабатываемых и развертываемых небольших служб, каждая из которых запускается в виде одного или нескольких изолированных процессов.
«Похоже на сервис-ориентированную архитектуру», – скажет проницательный читатель. Некоторое сходство, безусловно, есть. Сервис-ориентированная и микросервисная архитектура решают одну и ту же задачу – снижение сложности ИТ-ландшафта. Некоторые авторы считают, что микросервисы – это и есть правильно реализованная СОА. Однако я должен обратить ваше внимание на ряд ключевых различий между этими подходами.
Во-первых, в качестве программных интерфейсов для взаимодействия с микросервисами, как правило, используют RESTful API и асинхронный обмен сообщения через очереди (см. рисунок 1), а для реализации сервис-ориентированной архитектуры использовался протокол SOAP. Строго говоря, СОА не определяла способ взаимодействия между сервисами, но на момент её появления какой-либо реальной альтернативы использованию SOAP просто не существовало. Из-за этого логическая организация сервисов и микросервисов мало похожи друг на друга. Микросервисы реализуют возможность управления структурированным информационным ресурсом посредством ограниченного набора операций: чтения и обновления его отдельных частей, а все взаимодействия строятся без сохранения на сервере состояния клиента. СОА-сервисы не используют концепцию ресурса, а предоставляют собой набор операций над некоторыми объектами, которые четко нигде не определены. СОА-сервис – это набор из множества методов, выражаемых глаголами, инициирующих операции по созданию или модификации таких объектов.
Во-вторых, множество СОА-сервисов зачастую развертывались в одном процессе: сервере приложений, веб-сервере и сервисе интеграционной среды. Микросервисы же принято развертывать в изолированном окружении (см. рисунок 2). Если вы работали с открытым программным обеспечением, то наверняка привыкли к тому, что пакет установки включает в себя не только само приложение, но и дистрибутивы системы управления базой данных, веб-сервера, другого необходимого ПО, а также преднастроенные файлы конфигурации. Установка и запуск всех необходимых компонент полнофункционального решения производится буквально одной командой. Неважно, запускаете ли вы систему в облаке или на локальном компьютере. Такая организация ИТ-решений меняет жизненный цикл разработки и эксплуатации программных компонент, обеспечивая независимость командам разработки в выборе инструмента и способа организации данных с одной стороны и стирая различия между средой разработки и средой эксплуатации с другой.
Третье существенное отличие состоит в том функционале, который реализуется сервисом. В сервис-ориентированной архитектуре сервис – это повторно используемый компонент, реализующий некоторый одинаковый фрагмент, встречающийся в различных бизнес-процессах. Унифицировав бизнес-процесс или его часть, мы реализуем программный интерфейс к нему в виде сервиса. Это позволяет нам избавиться от дублирования кода, повысить концептуальную целостность приложения и снизить свои затраты на реализацию похожих задач. По крайней мере, такие цели декларировались в качестве задач внедрения сервис-ориентированной архитектуры. Микросервисы реализует конкретную бизнес-потребность. Мы не требуем от микросервиса многократного использования и не стремимся унифицировать бизнес-процесс. Скорее наоборот, микросервисы позволяют поддерживать необходимую вариативность процессов, предоставлять уникальный функционал для некоторого частного случая, возникшего при определенном стечении обстоятельств. Микросервисы – это идеальный инструмент для реализации обработчиков ошибок и исключений, возникших в ходе исполнения операций, расширений типичного хода событий дополнительными сценариями, поддержки новых или экспериментальных функций.
Я бы сравнил появление микросервисов в архитектуре информационных систем с переходом от функционального к объектно-ориентированному программированию при разработке ПО. До середины 90-х годов прошлого века разработка представляла собой написание пакетов функций, которые потом вызывались из основного приложения. Было крайне важным выделить из разных частей программы схожие фрагменты бизнес-логики и реализовать их в единой библиотеке. С появлением объектно-ориентированного подхода все поменялось. Общий функционал мы реализуем в базовом классе в виде набора данных, который можно расширить, и методов, которые можно в дальнейшем переопределить. Прикладной программист наследует свое приложение от готового класса, разрабатывая лишь небольшой объем нового кода для расширения некоторых методов. Точно так же микросервис «переопределяет» небольшую часть функционала вызвавшего его приложения. В микросервисе мы реализуем то, что не реализовано в исходном приложении или реализовано не совсем так, как надо. Этот принцип формулируется как «начните с монолитного приложения» (Monolith First) и является одним из главных ключей к пониманию микросервисной архитектуры.
Микросервисы: смена архитектурной парадигмы
Ряд характеристик микросервисов, таких как децентрализованный выбор стека технологий, или независимая организация, дают основания считать, что микросервисы – это то, что нарушает привычные правила «хорошей корпоративной архитектуры». Архитекторы предприятий на протяжении многих лет методично прививали организации набор определенных принципов. Часть из них нашла свой отражение в политиках и руководствах. Другая существует в виде неформальных договоренностей и соглашений. Третья – реализуется архитекторами непосредственно, в форме архитектурного надзора над проектами. Эти правила хорошо известны и многими из нас воспринимаются, как само собой разумеющиеся: необходимо стремиться к унификации серверов приложений, систем управления базами данных и инструментов разработки, избавляться от нескольких версий одного и того же программного средства, консолидировать информацию и приводить структуры данных к единому формату.
Принципы микросервисной архитектуры выглядят отрицанием всех этих идей. Каждый микросервис включает в себя свой стек технологий, выбор которого осуществляется непосредственным разработчиком. Вместо единой базы данных в каждом микросервисе используется собственный инструмент хранения информации, причем выбор реляционной или нереляционной СУБД, способа организации данных, атрибутивного состава и программных интерфейсов для предоставления данных также ни с кем не согласуется. Более того, сходные по своему характеру данные могут быть распределены по нескольким экземплярам микросервиса. Зачастую микросервис проще переписать заново, чем доработать, а добавление нового функционала в приложение предпочтительней реализовывать в виде нового микросервиса, а не посредством переработки уже существующего отлаженного кода.
Достаточно ли велики преимущества микросервисной архитектуры, чтоб мы разом отказались от своих архитектурных принципов? Можем ли мы начать использовать микросервисы только в одном из корпоративных приложений, не затрагивая другие, а решение об их полезности принимать по результатам пилотного проекта? Конечно, да. Именно так и следует выстраивать проект по внедрению микросервисов в корпоративный ИТ-ландшафт.
Микросервисы с точки зрения ИТ эксплуатации
Корпоративная информационная система – это живой организм, в котором постоянно что-то меняется. И после каждого изменения что-то может пойти не так. Поэтому основной стратегией предприятий в области управления изменениями долгое время оставалась минимизация их количества. Мы выстраиваем эшелонированную оборону против изменений, включающую множество барьеров: процедуры авторизации изменений, разнообразное тестирование релизов, разработку и согласование огромного объема документации.
Это все отлично работает, пока изменение не случилось. Но рано или поздно наступает момент, когда надо рискнуть и установить изменение. И в этот момент прежняя стратегия безопасности изменений становится совершенно бессмысленной и даже вредной. Часто мы не можем обнаружить и быстро, не дожидаясь ощутимого ущерба, исправить ошибку. Непонятно, в какой момент такая ошибка вылезет, и какое изменение следует откатить для её устранения. Так что корректирующее изменение нам придется делать по длинному циклу.
Стратегия управления изменениями в облачных инфраструктурах принципиально иная: мы часто ошибаемся, но быстро, не дожидаясь серьезных последствий, исправляем свои ошибки. По мере развития виртуализации и автоматизации эксплуатационных операций, с появлением в компаниях инфраструктуры «частного облака», новая стратегия управления изменениями постепенно проникает и в корпоративные информационные системы, что ведет к новым требованиям к архитектуре приложений.
Давайте подробнее рассмотрим эти требования. Основным требованием новой стратегии управления изменениями так же является безопасность. Но мы не говорим о превентивной безопасности. Речь не идет об исчерпывающем документировании, утверждении изменений на архитектурных советах и глубоком регрессионном тестировании. Нам нужно немного иное:
Наблюдаемость хода исполнения приложения. Архитектура системы должна предоставлять инструменты, способные обнаружить и даже прогнозировать отказы и сбои. Мы должны постоянно получать оповещения о здоровье приложения и четко понимать, какие значения измерений свидетельствуют о том, что что-то пошло не так.
Изоляция сбоев. Для того чтобы снизить риск наступления масштабного сбоя, необходимо ограничение размера функциональных компонент. Монолитное приложение обрушается целиком. В такой архитектуре какой-нибудь несущественный отчет, запускаемый раз в квартал, может стать причиной деградации системы массового обслуживания. Микросервисная архитектура снижает вероятность таких событий.
Устойчивость системы к отказам отдельных компонент. Сильная связность программных компонент может привести к каскадному обрушению системы в целом. Эта ситуация похожа на веерные отключения электроснабжения, когда из-за локального сбоя страдают большие группы потребителей услуг. Такое развитие событий особенно вероятно при работе с общей базой данных или использовании синхронных вызовов удаленных процедур. Например, несколько программ вызывают один и тот же сервис. В некоторый момент этот сервис оказывается недоступен. Приложения пытаются вызвать сервис повторно, и как только сервис восстановился, его тут же сметает волна неотработанных ранее запросов, и он снова ломается. Приложения более высокого уровня всё это время остаются недоступны, т.к. заблокированы ожиданием ответа из-за синхронного вызова веб-сервиса. Следующую волну нагрузки создадут раздосадованные пользователи, нажимающие кнопку обновления «зависшей» страницы в своих браузерах.
Автоматическое восстановление. Обнаружение и локализация отказов совершенно бесполезны, если вы не знаете, что с этим делать. Традиционный подход заключается в том, чтоб выдать сообщение об ошибке и как ни в чем не бывало продолжить работу. Зачастую программисты делают такие сообщения для себя. И их смысловая нагрузка ограничивается информацией о том, что что-то пошло не так. Если же такое сообщение не проявилось в ходе отладки, то код вместе с ним отправится в тестирование, а затем в «боевую» среду. Когда сложится ситуация, приводящая к такой ошибке, искать программиста будет уже поздно. Поэтому получателем сообщений об ошибке должна быть система, управляющая выполнением программного комплекса.
Архитектуру, отвечающих сформулированным требованиям, помогает построить так называемое сине-зеленое развертывание. Мы не станем устанавливать новый релиз микросервиса поверх существующего, а создадим еще одну виртуальную машину, в котором запустим новый экземпляр сервиса или развернем еще один контейнер. Затем мы перенаправим на него небольшую часть запросов, например, только от пользователей, которые участвуют в приемочном тестировании этого релиза. Если что-то пойдет не так, то мы в любой момент можем перевести запросы этой группы пользователей на предыдущую версию микросервиса. При этом речь не обязательно идет об ошибках в коде программного обеспечения. Причиной отказа от дальнейшей эксплуатации релиза могут являть логические ошибки проектирования, неверно сформулированные требования или просто негативная обратная связь от пользователей.
Но как не потерять данные, которые успели накопиться в неудачном релизе? Общего ответа на этот вопрос не существует, но есть несколько частных случаев, для которых эта задача легко решается. Один из распространенных шаблонов проектирования распределенных систем предписывает разделять запросы на чтение данных и команды на их модификацию (command-query responsibility segregation). Если наш микросервис был спроектирован в соответствии с этим принципом и обрабатывал только запросы на чтение, то никаких новых данных от пользователей он просто не накопил, и после возврата маршрутизации запросов на предыдущую версию сервиса новую неудачную версию мы может просто выключить. С обработкой команд задача немного сложнее. Тем не менее, команды на изменение данных обычно не обрабатываются синхронно, а помещаются в очереди сообщений. Это обеспечивают большую гибкость в организации логики обработки. Мы можем продублировать поток сообщений и сравнивать результаты их обработки разными версиями сервиса, сохранить часть сообщений для последующей обработки проверенной версией, написать обработчики для отмены изменений и сделать многое другое.
Построение таких архитектур требует дополнительных усилий, но окупает себя. Задача архитектора всегда заключалась в том, чтоб правильно разделить систему на компоненты так, чтоб их можно было создавать, развивать и заменять независимо друг от друга, силами небольших специализированных команд, использующих наиболее подходящий для конкретной задачи набор технологии. Эта задача никогда не была простой. Как мы можем предвидеть новые требования, которые будут сформулированы через год или два, строить прогнозы относительно успешности в будущем тех или иных технологий, разрабатывать структуры для пока еще не собранных данных? Ответ на этот вопрос дает еще одно свойство микросервисов – эволюционирующая архитектура. Речь идет об изначальном построении системы таким образом, чтоб в дальнейшем её развитие заключалось не в переработки существующих модулей, а в присоединении к приложению новых компонент и источников данных. Это чем-то напоминает архитектуру микроядра, используемую при разработке операционных систем. Микроядро реализует самое необходимое, а все прикладные функции в такой архитектуре выносятся во внешние модули. Только в случае операционных систем речь идет о драйверах устройств, функциях работы с файловыми системами и сетевых службах. В микросервисной архитектуре мы выносим во внешние подключаемые модули прикладной функционал. Это свойство микросервисов часто формулируют как «организация сервисов вокруг бизнес-возможностей».
Но, пожалуй, самым востребованным результатом перехода к микросервисной архитектуре будет структурирование процесса разработки приложений, выстраивание его в виде параллельной деятельности независимых agile-команд разработчиков. Распределение задач между такими командами, распределение ответственности, организация взаимодействия между командами определяется в этом случае самой архитектурой микросервисного приложения.
Варианты использования микросервисной архитектуры в организации
Если опросить компании, приступившие к использованию микросервисной архитектуры, для каких именно бизнес-приложений подходит этот архитектурный стиль, то среди лидеров будут системы дистанционного обслуживания – клиентские мобильные приложения и личные кабинеты, фронтальные системы, поддерживающие работу сотрудников отделений и контактного центра. Но эти приложения обычно не существуют сами по себе, а нуждаются в тесной интеграции с большим количеством бэк-офисных систем. Из них фронтальные и клиентские приложения черпают клиентские данные, в них же отправляют команды на совершение операций, оттуда же загружают бизнес-правила и основные справочники.
Проект создания «единого окна», интегрирующего в общий пользовательский интерфейс функционал десятка разрозненных приложений, никогда не был простыми. В рамках такого проекта сложно обойтись без обновления унаследованных приложений. Существующие системы не были предназначены для интеграции. Предполагалось, что с ними будут работать люди. Поэтому о хороших программных интерфейсах со стороны таких приложений остается только мечтать. Если программные интерфейсы и существуют, то они плохо абстрагированы, несут на себе печать конкретной реализации, а ограничения унаследованных систем по уровню доступности, количеству одновременных обращений или актуальности данных делают невозможным их практическое использование. Рядом с такой системой приходится создавать онлайновое хранилище данных и конвейер обработки событий. Впрочем, подобные затраты не являются чем-то напрасным, т.к. позволяют не только интегрировать такие системы в композитные ИТ-решения, предназначенные для клиентов или сотрудников, но и реализовывать новый функционал без внесения изменений в унаследованное приложение. Вы можете пользоваться уже имеющимися в системе функциями и данными, но реализовывать новые бизнес-процессы в отдельных изолированных от приложения микросервисах. Это намного более быстрая и экономически обоснованная альтернатива замены или полного переписывания устаревших систем.
Для микросервисной архитектуры есть и совершенно новые области применения, открывшиеся из-за появления аналитики больших данных, дигитализации бизнес-деятельности, формирования партнерских экосистем по построению новых цепочек создания ценности для клиента. Одной из таких областей является персонификация клиентских предложений, базирующаяся на сегментировании клиентской базы, формировании целевых предложений для небольших групп клиентов и постоянном тестировании гипотез о поведении той или иной группы. Объем предложений в продуктовом портфеле организаций при реализации такой стратегии вырастает в сотни и даже тысячи раз. Раньше для конкретного клиента предлагался некоторый базовый продукт и ограниченный набор дополнительных сервисов. Бизнес-логика и данные каждого продукта и сопутствующих ему опций реализовывались отдельным приложением. Сегодня компании стремятся предоставить клиенту ничем не ограниченное сочетание как своих, так и партнерских продуктов. Такие комбинации сложно реализовать в каком-то одном приложении. Необходимо согласованное внесение изменений сразу в несколько информационных систем. В таких случаях намного разумней вынести бизнес-логику и все относящиеся к новому предложению данные в отдельный компонент – микросервис, полностью реализующий требуемый функционал и управляющий поведением унаследованных приложений через программные интерфейсы.
Такой микросервис не обязательно встраивать в собственные приложения организации. Можно предоставить доступ к его программным интерфейсам приложениям ваших партнеров. Веб-приложение для взаимодействия с клиентом в этом случае разрабатывает партнер, а поток команд обрабатывает ваш микросервис. Так закладывается основа для развития партнерских экосистем, сложных цепочек создания ценности новых продуктов и услуг. Обладая достаточном количеством микросервисов с четко выраженными программными интерфейсам, хорошим уровнем доступности и сценариями масштабирования, организация закладывает основу для своей будущей платформы цифрового бизнеса.
Сегодня микросервисная архитектура – модная тема. Легко заявлять о своей приверженности этому направлению. Сложнее изменить подходы к разработке и эксплуатации корпоративных информационных систем. Еще сложнее изменить устоявшиеся принципы корпоративной архитектуры, критерии принятия решений, приступить к трансформации работающих бизнес-процессов и изменению ИТ-ландшафта. Как, когда и в каком объеме осуществить данную трансформацию, каждая организация будет определять сама, в зависимости от текущих целей, ситуации на рынке и имеющихся ресурсов. Уверен, что большинство компаний сделают этот выбор правильно. Ошибкой станет не отказ от использования микросервисов в том или ином приложении, а полное игнорирование или недостаточное понимание этого подхода, открывающего сегодня широчайший спектр возможностей в развитии корпоративных ИТ.
Это исходная (авторская) версия статьи, опубликованной в 21.11.2017 в журнале “Открытые системы. СУБД” https://www.osp.ru/os/2017/04/13053389/
RE ” Этот принцип формулируется как «начните с монолитного приложения» (Monolith First) и является одним из главных ключей к пониманию микросервисной архитектуры.” – вроде бы недавно это обсуждалось и согласились с тем что “Monolith First” это не принцип, а констатация факта.
“Не путай микросервисы с архитектурой” https://r3code.livejournal.com/228605.html
Что скажете об этом?