Поделиться через


"Шаблон использования шлюза API против прямого обмена данными между клиентом и микрослужбами"

Подсказка

Это фрагмент из электронной книги «Архитектура микрослужб .NET для контейнеризованных приложений .NET», доступной в документации .NET или в виде бесплатного скачиваемого PDF-файла, который можно прочитать в автономном режиме.

Архитектура микросервисов .NET для приложений .NET в контейнерах, миниатюра обложки электронной книги.

В архитектуре микрослужб каждая микрослужба включает набор (обычно) мелкозернистых конечных точек. Этот факт может повлиять на взаимодействие между клиентами и микрослужбами, как описано в этом разделе.

Прямая связь между клиентами и микрослужбами

Возможный подход — использовать прямую архитектуру обмена данными между клиентами и микрослужбами. В этом подходе клиентское приложение может выполнять запросы непосредственно к некоторым микрослужбам, как показано на рис. 4-12.

Схема, на которой показана архитектура связи между клиентами и микрослужбами.

Рис. 4-12. Использование архитектуры прямого взаимодействия клиента с микрослужбой

В этом подходе каждая микрослужба имеет общедоступную конечную точку, иногда с разными TCP-портами для каждой микрослужбы. Пример URL-адреса для конкретной службы может быть следующим URL-адресом в Azure:

http://eshoponcontainers.westus.cloudapp.azure.com:88/

В рабочей среде на основе кластера этот URL-адрес сопоставляется с подсистемой балансировки нагрузки, используемой в кластере, которая, в свою очередь, распределяет запросы по микрослужбам. В рабочих средах можно использовать контроллер доставки приложений (ADC), например шлюз приложений Azure между микрослужбами и Интернетом. Этот уровень выступает в качестве прозрачного уровня, который не только выполняет балансировку нагрузки, но и защищает службы, предлагая завершение SSL. Этот подход оптимизирует нагрузку на хосты, передавая ресурсоемкое завершение SSL и другие обязанности по маршрутизации шлюзу приложений Azure. В любом случае подсистема балансировки нагрузки и ADC прозрачны с точки зрения архитектуры логических приложений.

Прямая архитектура обмена данными между микрослужбами может быть достаточно хороша для небольшого приложения на основе микрослужб, особенно если клиентское приложение является серверным веб-приложением, таким как приложение ASP.NET MVC. Однако при создании крупных и сложных приложений на основе микрослужб (например, при обработке десятков типов микрослужб) и особенно при использовании клиентских приложений удаленных мобильных приложений или веб-приложений SPA этот подход сталкивается с несколькими проблемами.

При разработке большого приложения на основе микрослужб следует учитывать следующие вопросы:

  • Как клиентские приложения свести к минимуму количество запросов к серверной части и сократить взаимодействие с несколькими микрослужбами?

Взаимодействие с несколькими микрослужбами для создания одного экрана пользовательского интерфейса увеличивает количество обходных путей по Интернету. Этот подход повышает задержку и сложность на стороне пользовательского интерфейса. В идеале ответы должны эффективно объединяться на стороне сервера. Такой подход снижает задержку, так как несколько фрагментов данных возвращаются параллельно, и некоторый пользовательский интерфейс может отображать данные сразу после его готовности.

  • Как справиться с перекрестными проблемами, такими как авторизация, преобразования данных и отправка динамических запросов?

Реализация аспектов, таких как безопасность и авторизация, для каждой микрослужбы может потребовать значительных усилий в разработке. Возможный подход — иметь эти службы в узле Docker или внутреннем кластере, чтобы ограничить прямой доступ к ним извне и реализовать эти перекрестные проблемы в централизованном месте, например шлюз API.

  • Как клиентские приложения могут взаимодействовать со службами, используюющими протоколы, отличные от Интернета?

Протоколы, используемые на стороне сервера (например, AMQP или двоичные протоколы), не поддерживаются в клиентских приложениях. Таким образом, запросы должны выполняться через протоколы, такие как HTTP/HTTPS, и переведены в другие протоколы после этого. Человек в середине подхода может помочь в этой ситуации.

  • Как создать фасад специально для мобильных приложений?

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

Почему следует учитывать шлюзы API вместо прямого обмена данными между клиентами и микрослужбами

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

Таким образом, наличие промежуточного уровня или уровня косвенного (шлюза) может быть удобным для приложений на основе микрослужб. Если у вас нет шлюзов API, клиентские приложения должны отправлять запросы непосредственно в микрослужбы и возникают проблемы, такие как следующие проблемы:

  • Связь. Без шаблона шлюза API клиентские приложения связаны с внутренними микрослужбами. Клиентские приложения должны знать, как разложены несколько областей приложения в микрослужбах. При развитии и рефакторинге внутренних микрослужб эти действия сильно влияют на обслуживание, так как вызывают критические изменения в работе клиентских приложений из-за прямых ссылок на внутренние микрослужбы из этих приложений. Клиентские приложения необходимо обновлять часто, что затрудняет развитие решения.

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

  • Проблемы безопасности. Без шлюза все микрослужбы должны быть подвержены "внешнему миру", что делает поверхность атаки больше, чем при скрытии внутренних микрослужб, которые не используются непосредственно клиентскими приложениями. Чем меньше область атаки, тем безопаснее может быть ваше приложение.

  • Перекрестные проблемы: каждая публично опубликованная микрослужба должна обрабатывать такие проблемы, как авторизация и SSL. Во многих ситуациях эти проблемы могут обрабатываться на одном уровне, чтобы внутренние микрослужбы были упрощены.

Что такое шаблон шлюза API?

При разработке и создании больших или сложных приложений на основе микрослужб с несколькими клиентскими приложениями рекомендуется использовать шлюз API. Этот шаблон представляет собой службу, которая предоставляет одну точку входа для определенных групп микрослужб. Это похоже на шаблон "Фасад " из объектно-ориентированного дизайна, но в данном случае это часть распределенной системы. Шаблон шлюза API также иногда называется серверной частью интерфейсной части (BFF), так как вы создаете ее, думая о потребностях клиентского приложения.

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

На рисунке 4–13 показано, как настраиваемый шлюз API может вписываться в упрощенную архитектуру на основе микрослужб с несколькими микрослужбами.

Схема, показывающая шлюз API, реализованный как пользовательская служба.

Рис. 4-13. Использование шлюза API, реализованного как настраиваемая служба

Приложения подключаются к одной конечной точке, шлюзу API, настроенной для пересылки запросов к отдельным микрослужбам. В этом примере шлюз API будет реализован в качестве пользовательской службы ASP.NET Core WebHost, работающей в качестве контейнера.

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

При реализации шаблона шлюза API необходимо быть осторожным. Обычно не рекомендуется использовать один шлюз API, агрегирующий все внутренние микрослужбы приложения. Если это так, он действует как монолитный агрегат или оркестратор и нарушает автономию микрослужб путем объединения всех микрослужб.

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

При разбиении уровня шлюза API на несколько шлюзов API, если ваше приложение имеет несколько клиентских приложений, это может быть основным критерием при выявлении различных типов шлюзов API, чтобы вы могли создавать разные фасады для потребностей каждого клиентского приложения. Это шаблон с именем Backend for Frontend (BFF), где каждый шлюз API может предоставить другой API, адаптированный для каждого типа клиентского приложения, возможно, даже на основе форм-фактора клиента путем реализации определенного кода адаптера, который под ним вызывает несколько внутренних микрослужб, как показано на следующем рисунке:

Схема с несколькими пользовательскими шлюзами API.

Рис. 4-13.1. Использование нескольких пользовательских шлюзов API

На рисунке 4-13.1 показаны шлюзы API, разделенные по типу клиента; один для мобильных клиентов и один для веб-клиентов. Традиционное веб-приложение подключается к микрослужбе MVC, которая использует шлюз веб-API. В примере показана упрощенная архитектура с несколькими мелкозернистыми шлюзами API. В этом случае границы, определенные для каждого API-шлюза, основаны исключительно на модели "Серверная часть для внешнего интерфейса" (BFF) и, следовательно, исключительно на API, необходимом для каждого клиентского приложения. Но в более крупных приложениях вам также следует идти дальше и создавать дополнительные API-шлюзы, основанные на бизнес-границах, как второй точке опоры в дизайне.

Основные функции в шаблоне шлюза API

Шлюз API может предложить несколько функций. В зависимости от продукта, он может предлагать более богатые или более простые функциональные возможности, однако наиболее важными и базовыми для любого шлюза API являются следующие паттерны проектирования:

Обратная маршрутизация прокси-сервера или шлюза. Шлюз API предлагает обратный прокси-сервер для перенаправления или маршрутизации запросов (маршрутизация уровня 7, обычно HTTP-запросов) к конечным точкам внутренних микрослужб. Шлюз предоставляет одну конечную точку или URL-адрес клиентских приложений, а затем внутренне сопоставляет запросы с группой внутренних микрослужб. Эта функция маршрутизации помогает отделить клиентские приложения от микросервисов, и она удобно используется при модернизации монолитного API, помещая API шлюз между монолитным API и клиентскими приложениями. Так вы можете добавлять новые API как новые микросервисы, продолжая использовать устаревший монолитный API до его разделения на множество микросервисов в будущем. Благодаря шлюзу API, клиентские приложения не замечают, если используемые API реализованы как внутренние микросервисы или монолитный API. И более важно, при преобразовании и рефакторинге монолитного API в микросервисы клиентские приложения не будут затронуты изменениями URI благодаря маршрутизации через шлюз API.

Дополнительные сведения см. в разделе "Шаблон маршрутизации шлюза".

Агрегация запросов. В рамках шаблона шлюза можно объединить несколько клиентских запросов (обычно HTTP-запросов), предназначенных для нескольких внутренних микрослужб в один клиентский запрос. Этот шаблон особенно удобно, если клиентская страница или экран нуждается в информации из нескольких микрослужб. При таком подходе клиентское приложение отправляет один запрос шлюзу API, который отправляет несколько запросов во внутренние микрослужбы, а затем объединяет результаты и отправляет все обратно клиентскому приложению. Основное преимущество и цель этого шаблона проектирования заключается в сокращении чата между клиентскими приложениями и серверным API, что особенно важно для удаленных приложений из центра обработки данных, где микрослужбы живут, например мобильные приложения или запросы, поступающие из приложений SPA, поступающих из JavaScript в клиентских удаленных браузерах. Для обычных веб-приложений, выполняющих запросы в серверной среде (например, веб-приложение ASP.NET Core MVC), этот шаблон не так важен, так как задержка значительно меньше, чем для удаленных клиентских приложений.

В зависимости от используемого продукта шлюза API, он может выполнять это агрегирование. Однако во многих случаях это более гибко для создания микрослужб агрегирования в рамках шлюза API, поэтому определяется агрегирование в коде (т. е. код C#):

Дополнительные сведения см. в разделе "Шаблон агрегирования шлюза".

Перекрестные проблемы или разгрузка шлюза. В зависимости от возможностей, предлагаемых каждым продуктом шлюза API, можно выгрузить функциональные возможности отдельных микрослужб на шлюз, что упрощает реализацию каждой микрослужбы путем консолидации перекрестных проблем на один уровень. Этот подход особенно удобн для специализированных функций, которые могут быть сложными для правильной реализации в каждой внутренней микрослужбе, таких как следующие функции:

  • Проверка подлинности и авторизация
  • Интеграция обнаружения сервисов
  • кэширование ответов;
  • Политики повторных попыток, разбиение цепи и QoS
  • Ограничение скорости запросов и ограничение нагрузки
  • Балансировка нагрузки
  • Ведение журнала, трассировка, корреляция
  • Заголовки, строки запроса и преобразование утверждений
  • Список разрешенных IP-адресов

Дополнительные сведения см. в разделе "Шаблон разгрузки шлюза".

Использование продуктов с функциями шлюза API

В зависимости от каждой реализации могут возникнуть более разнообразные проблемы, предлагаемые продуктами шлюзов API. Мы рассмотрим здесь:

Управление API Azure

Управление API Azure (как показано на рис. 4-14) не только решает потребности шлюза API, но и предоставляет такие функции, как сбор аналитических сведений из API. Если вы используете решение для управления API, шлюз API является только компонентом в этом полном решении по управлению API.

Схема, показывающая, как использовать управление API Azure в качестве шлюза API.

Рис. 4-14. Использование службы "Управление API Azure" для шлюза API

Управление API Azure решает ваши потребности как в шлюзе API, так и в их управлении, такие как ведение журнала, безопасность, учет и т. д. В этом случае, при использовании продукта, такого как управление API Azure, наличие единственного шлюза API не столь рискованным, поскольку такого рода шлюзы API являются "более тонкими", то есть вы не реализуете пользовательский код на C#, который мог бы перерасти в монолитный компонент.

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

Аналитические сведения, доступные в системе управления API, помогают понять, как используются API и как они выполняются. Они делают это, позволяя просматривать отчеты аналитики в режиме реального времени и выявлять тенденции, которые могут повлиять на ваш бизнес. Кроме того, вы можете иметь журналы о действиях запроса и ответа для дальнейшего интерактивного и автономного анализа.

С помощью службы "Управление API Azure" вы можете защитить API с помощью ключа, маркера и фильтрации IP-адресов. Эти функции позволяют применять гибкие и точные квоты и ограничения скорости, изменять форму и поведение API с помощью политик и повысить производительность при кэшировании ответов.

В этом руководстве и эталонном примере приложения (eShopOnContainers) архитектура ограничена более простой и настраиваемой контейнерной архитектурой, чтобы сосредоточиться на простых контейнерах без использования продуктов PaaS, таких как управление API Azure. Но для крупных приложений на основе микрослужб, развернутых в Microsoft Azure, мы рекомендуем оценить управление API Azure в качестве основы для шлюзов API в рабочей среде.

Оцелот

Ocelot — это упрощенный шлюз API, рекомендуемый для более простых подходов. Ocelot — это шлюз API на основе .NET Core с открытым кодом, особенно сделанный для архитектур микрослужб, которым требуются унифицированные точки входа в свои системы. Эта легковесная, быстрая и масштабируемая система обеспечивает маршрутизацию, аутентификацию и множество других функций.

Основная причина выбора Ocelot для эталонного приложения eShopOnContainers 2.0 заключается в том, что Ocelot — это упрощенный шлюз API .NET Core, который можно развернуть в той же среде развертывания приложений, где развертываются микрослужбы и контейнеры, такие как узел Docker, Kubernetes и т. д. И так как он основан на .NET Core, он кроссплатформенный, позволяющий развертывать в Linux или Windows.

На предыдущих схемах, которые демонстрируют пользовательские шлюзы API, работающие в контейнерах, показано, как можно запускать Ocelot в контейнере и в приложении, основанном на микросервисах.

Кроме того, на рынке есть множество других продуктов, предлагающих функции шлюзов API, таких как Apigee, Kong, MuleSoft, WSO2, а также другие продукты, такие как Linkerd и Istio для контроллеров входа сетки служб.

В следующих разделах описано, как реализовать шлюзы API с помощью Ocelot.

Недостатки шаблона шлюза API

  • Наиболее важным недостатком является то, что при реализации шлюза API этот уровень связан с внутренними микрослужбами. Подобная связь может привести к серьезным трудностям в вашем приложении. Clemens Vaster, архитектор команды Azure Service Bus, называет эту потенциальную трудность "новым ESB" в сессии "Обмен сообщениями и микрослужбы" на GOTO 2016.

  • С помощью шлюза API микрослужб создается дополнительная возможная единая точка сбоя.

  • Шлюз API может привести к увеличению времени отклика из-за дополнительного сетевого вызова. Однако этот дополнительный вызов обычно оказывает меньше влияния, чем наличие клиентского интерфейса, который слишком болтливый и напрямую вызывает внутренние микрослужбы.

  • Если правильно не масштабировать, шлюз API может стать узким местом.

  • Шлюз API требует дополнительных затрат на разработку и дальнейшее обслуживание, если он включает в себя настраиваемую логику и агрегирование данных. Разработчики должны обновить шлюз API для предоставления конечных точек каждой микрослужбы. Кроме того, изменения реализации во внутренних микрослужбах могут привести к изменению кода на уровне шлюза API. Однако если шлюз API просто применяет безопасность, логирование и управление версиями (как при использовании службы управления API Azure), это дополнительная стоимость разработки может не применяться.

  • Если шлюз API разрабатывается одной командой, может быть узкое место в разработке. Этот аспект является еще одной причиной, почему лучший подход заключается в наличии нескольких детализированных шлюзов API, которые реагируют на различные потребности клиентов. Вы также можете разделить шлюз API внутри нескольких областей или слоев, принадлежащих разным командам, работающим на внутренних микрослужбах.

Дополнительные ресурсы