9.1 Общие положения ГОСТ Р 70860—2023
Архитектура микросервисов представляет собой подход к построению облачного приложения. Облачное приложение специально создается для работы в облаке, а также для использования функциональных возможностей и среды облачных сервисов. Архитектура микросервисов является стилем архитектуры, предполагающим разбиение приложения на микросервисы, которые могут быстро и независимо друг от друга быть развернуты на любом инфраструктурном ресурсе по мере необходимости. В архитектуре микросервисов приложение разделяется на ряд отдельных процессов, называемых микросервисами, которые развертываются независимо и связываются друг с другом с помощью сервисных интерфейсов. Идея заключается в том, что микросервисы в рамках приложения предназначены для выполнения определенной области функций, например конкретного бизнес-процесса или определенной технической функциональной возможности. Эта архитектура позволяет использовать и обновлять каждый микросервис отдельно друг от друга. Таким образом, архитектура микросервисов является зонтичным методом, в которой микросервисы выступают в качестве основных компонентов.
Примечание — Термины «сервис» (услуга) и «сервисный интерфейс» используются в соответствии с определениями, приведенными в ГОСТ Р ИСО/МЭК 18384-1. Стандарт также содержит понятное объяснение сервис-ориентированной архитектуры, конкретным примером которой является архитектура микросервисов. Сервис или микросервис не следует путать с облачным сервисом. Может возникнуть ситуация, когда микросервис реализуется как облачный сервис, но это зависит исключительно от выбора разработчика приложения, и никаких определенных требований здесь нет.
Простой пример приложения, основанного на микросервисах, приведен на рисунке 4. В данном примере приложение состоит из ядра и двух микросервисов, один из которых работает с учетными записями пользователей, а второй занимается отображением и управлением видеорядом. В примере также показывается, что приложения микросервисов могут также использовать другие сервисы, как правило облачные, предоставляющие функциональные возможности, необходимые приложению. Поэтому в этом примере микросервис учетной записи пользователя использует сервис базы данных для хранения и получения информации об учетной записи; микросервис отображения видео использует сервис хранения видео, который хранит видеоряд; основное приложение использует сервис электронной почты, сервис Twitter-ленты и сервис аналитики.
Рисунок 4 — Пример приложения, структурированного с использованием архитектуры микросервисов
Важно понимать, что архитектура микросервисов — это метод, а также, что микросервисы являются основной частью архитектуры микросервисов. В этом и заключается отличие от технологий, которые могут быть использованы для реализации микросервисов. Микросервисы могут быть реализованы с помощью контейнеров, ВМ или бессерверных вычислений и подключены с помощью виртуализированных сетей, но этот подход отличается от метода, используемого для создания приложений.
Часто в контексте предметно-ориентированного проектирования использование функциональной декомпозиции является залогом построения успешной архитектуры микросервисов. Есть мнение, что эта архитектура представляет собой усовершенствованную и упрощенную версию сервис-ориентированной архитектуры (SOA). Архитектура микросервисов имеет следующие особенности:
- каждый архитектурный компонент («сервис») имеет четко определенный и явно обозначенный интерфейс;
- каждый сервис работает полностью автономно;
- изменение реализации сервиса не влияет на другие сервисы, поскольку обмен данными между сервисами происходит только через интерфейсы (обычно REST-интерфейс);
- слабая связанность и высокая связаность между сервисами позволяет создавать несколько сервисов для определения сервисов или приложений более высокого уровня.
Приложения на основе микросервисов отличаются от монолитных приложений, в которых все компоненты приложения создаются и собираются в рамках одного процесса, что характерно для более старых, необлачных корпоративных приложений [из 9.1 Общие положения ГОСТ Р 70860—2023]
9.2 Преимущества и недостатки микросервисов ГОСТ Р 70860—2023
Преимуществами микросервисной архитектуры являются:
- более простые кодовые базы для отдельных сервисов;
- возможность обновления и масштабирования каждого сервиса в отдельности;
- возможность написания сервисов на разных языках для удовлетворения потребностей в высокой скорости работы и удобства разработки (это называется «многоязычное программирование»);
- использование различных стеков промежуточного ПО и даже различных уровней данных для различных сервисов (высокая гибкость работы).
Одним из преимуществ использования архитектуры микросервисов является то, что каждый компонент приложения, построенный как микросервис, может быть масштабирован отдельно, чтобы соответствовать нагрузке именно на этот компонент. В подходе, используемом для создания монолитных приложений, такая возможность отсутствует. В архитектуре монолитного приложения все компоненты развертываются и работают как единое целое, а масштабирование возможно только путем увеличения или уменьшения масштаба всего приложения. Это может привести к снижению эффективности использования ресурсов для тех компонентов приложения, для которых высокая нагрузка отсутствует.
Системы PaaS позволяют легко развернуть каждый микросервис по отдельности и связать их вместе для создания полноценного приложения. Каждый микросервис может управляться независимо: масштабироваться, распределяться, обновляться.
Еще одним преимуществом использования архитектуры микросервисов является то, что каждый компонент приложения, построенный как микросервис, может иметь независимый жизненный цикл разработки. Это позволяет создавать более компактные компоненты приложений, которые можно быстрее модифицировать, расширять, тестировать и развертывать.
Кроме преимуществ есть еще и недостатки, которые для реализации всего потенциала преимуществ необходимо устранить. Краткое описание этих недостатков:
а) оптимизация обмена данными. Работа приложения в разных процессах приводит к увеличению объема передаваемых данных в связи с большим количеством вызовов API между сервисами по сравнению с вызовами функций, передаваемыми внутри процесса. Чтобы исправить ситуацию, необходимо определить оптимальный протокол, ожидаемое время отклика, значения тайм-аутов и конструкцию API. Для этого могут использоваться такие программные компоненты, как API-шлюз (см. 9.7), автоматические размыкатели (см. 9.6), балансировщики нагрузки (см. 14.2) и прокси-серверы (см. 14.2);
б) обнаружение сервисов. Обнаружение сервисов означает возможность сервисов согласованно обнаруживать друг друга. Для того чтобы сервисы могли регистрировать и объявлять себя, необходимо внедрить стандартизированный и согласованный рабочий процесс. Сервисы должны быть способны обнаруживать конечные устройства и местоположение других сервисов. Необходимо использовать спецификацию, которая будет определять порядок настройки шлюзов API для информирования о доступности сервисов и сохранения возможности обнаружения;
в) скорость работы. Выполнение одного функционального бизнес-требования может подразумевать оркестрацию сразу нескольких вызовов сервисов. Это может увеличить задержку отклика. Кроме того, данные, которые часто используются одним микросервисом, могут принадлежать другому микросервису. Для того чтобы избежать возникновения большого объема передаваемых данных, связанных с копированием данных при вызове сервисов, необходимо наличие функций совместного использования и синхронизации данных;
г) отказоустойчивость. Отказоустойчивость — это способность системы восстанавливаться после частичного отказа. Разработчикам микросервисов необходимо предложить механизмы для восстановления или остановки распространения сбоя на другие части системы. Кроме того, некоторые сервисы выполняются в нескольких копиях для обеспечения высокой масштабируемости и доступности. Ключевыми факторами для обеспечения отказоустойчивости являются количество копий, согласованность версий между копиями, механизм балансировки нагрузки и расположение сети;
д) безопасность. Критически важным решением является формирование доверительных отношений между микросервисами на основе различных способов, доступных сервисам для обмена данными друг с другом. Сервис может использовать синхронный или асинхронный протокол при вызове другого сервиса. Все эти факторы необходимо учитывать при назначении цепочек авторизации в токенах доступа. Схемы обмена данными между сервисами должны иметь специальные и эффективные механизмы аутентификации и авторизации, созданные на базе политик безопасности на базе управления рисками. Увеличение объема данных, передаваемых между компонентами [см. перечисление а)], требует использования защищенных коммуникационных протоколов, отвечающих требованиям приложения;
е) трассировка и протоколирование. При разбиении монолитных приложений на отдельные микросервисы возникает необходимость в дополнительных методах и решениях для отладки и профилирования систем. Один из таких методов называется «распределенная трассировка». Она отслеживает цепочку вызовов сервисов для поиска отдельной бизнес-транзакции или отдельного пользовательского запроса. Для получения целостного представления о работе системы обычно требуется центральная система протоколирования, которая поддерживает функцию агрегации для объединения информации из журналов отдельных микросервисов;
ж) развертывание. Распространение сервисных процессов требует наличия автоматизированных механизмов развертывания. Масштабируемость и целостность системы являются основными вопросами, которые необходимо учитывать при развертывании микросервисов. Контейнеры являются ключевым механизмом, используемым для развертывания микросервисов, а использование CMS (см. 7.4) (которая назначает ресурсы и реализует топологию соединений) решает проблемы развертывания. При этом отдельные предположения и требования моделей развертывания могут плохо сочетаться с функциональными требованиями отдельных приложений на базе микросервисов. В качестве примера можно предположить, что контейнер, в котором размещается микросервис, не имеет состояния. При этом общие требования к системе или приложению требуют наличия микросервиса, который имеет состояние;
и) функциональная декомпозиция. При декомпозиции монолитного приложения необходимо решить следующие вопросы:
1) правильное разграничение различных сервисов;
2) разделение сервиса на отдельные части, если он слишком объемный.
[из 9.2 Преимущества и недостатки микросервисов ГОСТ Р 70860—2023]
9.3 Спецификация микросервисов ГОСТ Р 70860—2023
Проектирование архитектуры микросервисов требует использования диаграмм описания и платформенно нейтральных языков описания из-за неоднородности при проектировании микросервисов компонентов. Хотя язык моделирования UML преимущественно используется для диаграмм описания, обычно применяются следующие языки:
- стандартные языки моделирования, такие как RAML и YAML;
- стандартные языки спецификаций, такие как JavaScript (Node.js), JSON и Ruby;
- псевдокод для алгоритмов;
- язык спецификации интерфейса, нейтральный к реализации, например спецификация Open API (www.openapis.org/).
[из 9.3 Спецификация микросервисов ГОСТ Р 70860—2023]
9.4 Многоуровневая архитектура ГОСТ Р 70860—2023
В программировании часто используются предметно-ориентированное проектирование и соответствующая многоуровневая архитектура (см. www.nareshbhatia.dev/articles/domain-driven-design-6-layered-architecture).
Благодаря функциональному разделению приложений на отдельные уровни многоуровневая архитектура обеспечивает следующие преимущества:
- эффективную совместную работу: каждый уровень разрабатывается специалистом, специализирующимся именно на данном уровне, например: графический интерфейс пользователя на основе веб-браузера разрабатывается веб-дизайнерами, а логика предметной области — программистами Java™. Специалисты могут сосредоточиться на своих собственных разработках при минимуме посторонних проблем;
- простое обслуживание: программный код каждого уровня логически независим от программного кода других уровней. Если программисты не нарушают интерфейсы на других уровнях, можно легко менять программный код;
- возможность повторного использования: в многоуровневой архитектуре: одно приложение разбивается на небольшие компоненты. Мелкие программные компоненты гораздо лучше подходят для повторного использования, чем крупные.
Использование многоуровневой архитектуры оказывается эффективным в приложениях на базе микросервисов. Многоуровневая архитектура используется в приложениях, разработанных с использованием микросервисов, и отдельные методы, связанные с использованием многоуровневой архитектуры, достаточно подробно описываются в литературе. Хотя для микросервисов не существует стандартизированной многоуровневой архитектуры, может быть использована многоуровневая архитектура, предложенная в предметно-ориентированном проектировании, суть которой можно выразить с помощью четырех уровней компонентов (см. рисунок 5):
- пользовательский интерфейс. Программный компонент принимает запросы от пользователей и предоставляет ответы;
- приложение. Программный компонент определяет границу приложения. Он представляет собой конечную точку взаимодействия с клиентами и осуществляет обработку запросов и ответов, вызов логики предметной области и управление контекстами транзакций;
- предметная область. Программный компонент реализует бизнес-логику;
- инфраструктура. Программный компонент инкапсулирует физические ресурсы, включая данные, и предоставляет уровню предметной области абстрактный интерфейс для доступа к данным.
Рисунок 5 — Многоуровневая архитектура, используемая с микросервисами
Каждый компонент, показанный на рисунке 5, представляет собой отдельный микросервис, работающий в своем собственном процессе и вызывающий другие микросервисы по мере необходимости.
Монолитные веб-приложения ранее разрабатывались на основе многоуровневой архитектуры, известной в виде шаблона «модель — представление — контроллер» (см. рисунок 6). Однако существуют некоторые различия в реализации многоуровневой архитектуры между приложением, разработанным с использованием микросервисов, и приложением с монолитной конструкцией. Они связаны с упаковкой программных компонентов и средами выполнения приложения.
Рисунок 6 — Модель монолитного веб-приложения
При проектировании монолитных приложений, хотя приложение разрабатывается и реализуется на основе многоуровневой архитектуры, все программные компоненты собираются в один программный пакет и развертываются в одной среде выполнения приложения. При условии, если веб-дизайнер добавляет небольшое обновление в графический интерфейс, необходимо собрать и протестировать весь программный пакет, причем серверная среда выполнения должна быть остановлена для развертывания нового программного пакета. Это может занять достаточно много времени, даже в случае небольшого изменения приложения.
С другой стороны, при проектировании приложения микросервисов каждый программный компонент на каждом уровне упаковывается как отдельный микросервис и независимо развертывается в отдельном процессе. Каждый процесс может быть реализован с помощью ВМ, контейнера или в виде бессерверных функций, каждая из которых может быть запущена и остановлена отдельно. Если каждый микросервис спроектирован правильно и имеет слабосвязанную архитектуру, разработчик может обновить один компонент без необходимости собирать, тестировать или повторно развертывать другие микросервисы. Архитектура микросервисов позволяет легко вносить изменения в приложение [из 9.4 Многоуровневая архитектура ГОСТ Р 70860—2023]
9.5 Сервисная сетка ГОСТ Р 70860—2023
В архитектуре микросервисов количество связанных с приложением микросервисов может быть достаточно большим. Обычно в таких случаях каждый сервис работает с несколькими экземплярами с кластерной конфигурацией — каждый экземпляр с отдельным процессом, реализованным в виде ВМ или контейнера. Количество процессов может во много раз превышать количество сервисов. Таким образом, общая топология может представлять собой сложную сеть, называемую сервисной сеткой (см. рисунок 7).
Рисунок 7 — Сервисная сетка для приложения, основанного на микросервисах
Для того чтобы приложение на основе микросервисов работало, и можно было пользоваться всеми его преимуществами, необходимо решить вопросы, связанные с сервисной сеткой:
а) управление трафиком:
1) точная балансировка нагрузки для конкретной версии микросервиса;
2) использование «синего»/«зеленого» методов развертывания для обновления микросервиса без остановки работы приложения;
3) ограниченный релиз;
4) автоматический размыкатель (см. 9.6);
б) обнаружение сервисов:
1) регистрация сервисов;
2) поиск сервисов;
в) тестирование:
1) внесение неисправностей;
г) безопасность:
1) аутентификация;
2) авторизация;
3) шифрование;
д) телеметрия:
1) интеграция функций протоколирования и трассировки;
2) интеграция метрик;
3) информационная панель.
В отношении управления сервисной сеткой существуют и другие подходы:
а) API;
б) среда сервисной сетки.
При подходе с использованием API разработчики приложений используют в своих программах определенный API для управления сервисной сеткой. Однако для этого разработчикам приходится тратить силы на реализацию нефункциональных требований в той же степени, как и функциональных, и в результате в код приложения включаются нефункциональные элементы реализации, что противоречит принципу разделения обязанностей в программировании и делает код более сложным и трудно модифицируемым. Примером API сервисной сетки является Eclipse Foundation API MicroProfile.
Среда сервисной сетки — это решение для инфраструктуры приложений, расположенное под уровнем приложений и над уровнем оркестрации, которое обрабатывает весь трафик между микросервисами. Эта среда управляет сервисной сеткой, контролируя проходящий трафик. Благодаря этому прикладная программа освобождается от реализации функциональных возможностей, необходимых для управления сервисной сеткой. Примеры реализаций среды сервисной сетки доступны по адресам: istio.io/ и linkerd.io/ [из 9.5 Сервисная сетка ГОСТ Р 70860—2023]
9.6 Автоматический размыкатель ГОСТ Р 70860—2023
Автоматический размыкатель — это шаблон проектирования, а также программный компонент, основанный на этом шаблоне.
Автоматический размыкатель применяется, когда один программный компонент вызывает другой программный компонент (например, микросервис) через API. Эти программные компоненты работают в разных процессах, а вызов API обычно происходит по сети. Такие удаленные вызовы API могут не сработать или остаться без ответа. Если целевым программным компонентом является часто используемый сервис, это может привести к целой серии отказов во всем приложении или системе.
Принцип работы автоматического размыкателя заключается в том, что любой такой удаленный вызов API скрывается компонентом автоматического размыкателя, который фактически является частью клиентского программного компонента. Когда клиент выполняет вызов API, он обрабатывается компонентом автоматического размыкателя, который следит за возможными сбоями. При обнаружении сбоя автоматический размыкатель отправляет сообщение об ошибке на API. В таких ситуациях автоматический размыкатель может также создавать предупреждения в целях мониторинга. Автоматический размыкатель может продолжать контролировать API и целевой компонент на предмет доступности и автоматически выключаться после устранения проблемы.
Определение ошибки может выполняться по-разному для разных автоматических размыкателей. Кроме того, они могут иметь настраиваемые параметры, которые регулируют их работу (например, порог ошибки, порог тайм-аута).
Автоматический размыкатель не избавляет клиентский компонент от необходимости решения проблемы со сбоем вызова API, но облегчает разработку соответствующих механизмов для устранения неполадок [из 9.6 Автоматический размыкатель ГОСТ Р 70860—2023]
9.7 API-шлюз ГОСТ Р 70860—2023
API-шлюз представляет собой программный компонент, который может использоваться для создания единого интегрированного API для набора микросервисов, которые совместно используются определенным клиентским компонентом.
Каждый микросервис имеет свой собственный API, основанный на его функциональных возможностях. Для решения своих рабочих задач конкретный клиент может использовать целую серию микросервисов. У клиентского ПО могут возникать сложности с обработкой различных вызовов API, которые необходимо отправлять на различные микросервисы. Для решения этой проблемы был разработан API-шлюз. Он предлагает клиентскому ПО более простой и согласованный API и вызывает API микросервисов по мере необходимости. Таким образом, API-шлюз представляет собой компонент, ориентированный на клиента. Для удовлетворения требований различных клиентов может потребоваться несколько различных АРI-шлюзов [из 9.7 API-шлюз ГОСТ Р 70860—2023]