Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Подсказка
Это фрагмент из электронной книги «Архитектура микрослужб .NET для контейнеризованных приложений .NET», доступной в документации .NET или в виде бесплатного скачиваемого PDF-файла, который можно прочитать в автономном режиме.
Это важно
В настоящее время эталонное приложение микрослужбы eShopOnContainers использует функции, предоставляемые Envoy для реализации шлюза API вместо более ранней ссылки на Ocelot. Мы выбрали этот вариант проектирования из-за встроенной поддержки протокола WebSocket, необходимого для новых коммуникаций gRPC, реализованных в eShopOnContainers. Однако мы сохранили этот раздел в руководстве, чтобы вы могли рассматривать Ocelot как простой, способный и упрощенный шлюз API, подходящий для сценариев производственного уровня. Кроме того, последняя версия Ocelot содержит критическое изменение в схеме json. Рекомендуется использовать Ocelot < версии 16.0.0 или использовать ключевые маршруты вместо reRoutes.
Разработка и проектирование шлюзов API
На следующей схеме архитектуры показано, как шлюзы API были реализованы с помощью Ocelot в eShopOnContainers.
Рис. 6–28. Архитектура eShopOnContainers с шлюзами API
На этой схеме показано, как все приложение развертывается на одном узле Docker или на компьютере разработки с помощью Docker для Windows или Docker для Mac. Однако развертывание в любом оркестраторе будет аналогично, но любой контейнер на схеме можно масштабировать в оркестраторе.
Кроме того, ресурсы инфраструктуры, такие как базы данных, кэш и брокеры сообщений, должны быть загружены из оркестратора и развернуты в высокодоступных системах для инфраструктуры, таких как База данных SQL Azure, Azure Cosmos DB, Azure Redis, служебная шина Azure или любое решение кластеризации высокого уровня доступности в локальной среде.
Как вы также можете заметить на схеме, наличие нескольких шлюзов API позволяет нескольким командам разработчиков быть автономными (в этом случае функции маркетинга и покупки) при разработке и развертывании микрослужб, а также собственных связанных шлюзов API.
Если у вас есть один монолитный шлюз API, который будет означать, что одна точка будет обновлена несколькими командами разработчиков, которые могут сочетать все микрослужбы с одной частью приложения.
Гораздо дальше в проектировании иногда более точно настроенный шлюз API также может быть ограничен одной бизнес-микрослужбой в зависимости от выбранной архитектуры. Наличие границ шлюза API, диктуемых бизнесом или доменом, поможет вам улучшить дизайн.
Например, детализация на уровне шлюза API особенно полезна для более сложных составных приложений пользовательского интерфейса, основанных на микрослужбах, так как концепция тонкого шлюза API похожа на службу композиции пользовательского интерфейса.
Дополнительные сведения см. в предыдущем разделе "Создание составного пользовательского интерфейса на основе микрослужб".
В качестве ключа для многих средних и крупных приложений, использование пользовательского продукта шлюза API обычно является хорошим подходом, но не как единый монолитный агрегат или уникальный центральный пользовательский шлюз API, если только шлюз API не разрешает несколько независимых областей конфигурации для нескольких команд разработчиков, создающих автономные микрослужбы.
Примеры микрослужб и контейнеров для повторного перенаправления через шлюзы API
Например, eShopOnContainers имеет около шести внутренних типов микрослужб, которые должны быть опубликованы через шлюзы API, как показано на следующем рисунке.
Рис. 6–29. Папки микрослужб в решении eShopOnContainers в Visual Studio
О службе удостоверений, в проектировании она остается вне маршрутизации шлюза API, так как это единственная перекрестная проблема в системе, хотя с Ocelot его также можно включить в состав списков перенаправки.
Все эти службы в настоящее время реализуются как ASP.NET службы веб-API Core, как можно сказать из кода. Давайте сосредоточимся на одном из микрослужб, таких как код микрослужб каталога.
Рис. 6–30. Пример микрослужбы веб-API (микрослужба каталога)
Вы можете увидеть, что микрослужба каталога — это типичный проект веб-API ASP.NET Core с несколькими контроллерами и методами, как показано в следующем коде.
[HttpGet]
[Route("items/{id:int}")]
[ProducesResponseType((int)HttpStatusCode.BadRequest)]
[ProducesResponseType((int)HttpStatusCode.NotFound)]
[ProducesResponseType(typeof(CatalogItem),(int)HttpStatusCode.OK)]
public async Task<IActionResult> GetItemById(int id)
{
if (id <= 0)
{
return BadRequest();
}
var item = await _catalogContext.CatalogItems.
SingleOrDefaultAsync(ci => ci.Id == id);
//…
if (item != null)
{
return Ok(item);
}
return NotFound();
}
HTTP-запрос будет выполнять такой код C#, который обращается к базе данных микрослужбы и любому дополнительному необходимому действию.
В отношении URL-адреса микрослужбы, когда контейнеры развертываются на локальном компьютере разработки (локальный узел Docker), контейнер каждой микрослужбы всегда имеет внутренний порт (обычно порт 80), указанный в его dockerfile, как показано в следующем dockerfile:
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
WORKDIR /app
EXPOSE 80
Порт 80, показанный в коде, является внутренним в узле Docker, поэтому он не может быть достигнут клиентскими приложениями.
Клиентские приложения могут получить доступ только к внешним портам (при наличии), опубликованным при развертывании.docker-compose
Эти внешние порты не должны публиковаться при развертывании в рабочей среде. По этой причине, почему вы хотите использовать шлюз API, чтобы избежать прямого взаимодействия между клиентскими приложениями и микрослужбами.
Однако при разработке необходимо получить доступ к микрослужбе или контейнеру напрямую и запустить его через Swagger. Именно поэтому в eShopOnContainers внешние порты по-прежнему указываются, даже если они не будут использоваться шлюзом API или клиентскими приложениями.
Ниже приведен пример docker-compose.override.yml
файла микрослужбы каталога:
catalog-api:
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_URLS=http://0.0.0.0:80
- ConnectionString=YOUR_VALUE
- ... Other Environment Variables
ports:
- "5101:80" # Important: In a production environment you should remove the external port (5101) kept here for microservice debugging purposes.
# The API Gateway redirects and access through the internal port (80).
Вы можете увидеть, как в конфигурации docker-compose.override.yml внутренний порт для контейнера каталога является портом 80, но порт для внешнего доступа равен 5101. Но этот порт не должен использоваться приложением при использовании шлюза API только для отладки, запуска и тестирования только микрослужбы каталога.
Как правило, вы не будете развертывать с docker-compose в рабочей среде, так как правильная рабочая среда развертывания для микрослужб — это оркестратор, такой как Kubernetes или Service Fabric. При развертывании в этих средах используются разные файлы конфигурации, в которых вы не будете публиковать напрямую внешний порт для микрослужб, но всегда будете использовать обратный прокси-сервер из шлюза API.
Запустите микрослужбу каталога в локальном узле Docker. Либо запустите полное решение eShopOnContainers из Visual Studio (выполняется все службы в файлах docker-compose), либо запустите микрослужбу каталога с помощью следующей команды docker-compose в CMD или PowerShell, размещенной в папке, в которой docker-compose.yml
размещается каталог docker-compose.override.yml
.
docker-compose run --service-ports catalog-api
Эта команда выполняет только контейнер службы api каталога и зависимости, указанные в docker-compose.yml. В этом случае контейнер SQL Server и контейнер RabbitMQ.
Затем вы можете напрямую получить доступ к микрослужбе каталога и просмотреть его методы через пользовательский интерфейс Swagger, который обращается непосредственно через этот внешний порт, в этом случае http://host.docker.internal:5101/swagger
:
Рис. 6–31. Тестирование микрослужбы каталога с помощью пользовательского интерфейса Swagger
На этом этапе можно задать точку останова в коде C# в Visual Studio, протестировать микрослужбу с помощью методов, предоставляемых в пользовательском интерфейсе Swagger, и, наконец, очистить все с помощью docker-compose down
команды.
Однако прямой доступ к микрослужбе, в данном случае через внешний порт 5101, является именно тем, что вы хотите избежать в приложении. И вы можете избежать этого, задав дополнительный уровень косвенного обращения шлюза API (Ocelot, в данном случае). Таким образом, клиентское приложение не будет напрямую обращаться к микрослужбе.
Реализация шлюзов API с помощью Ocelot
Ocelot — это в основном набор ПО промежуточного слоя, который можно применить в определенном порядке.
Ocelot предназначен для работы только с ASP.NET Core. Последняя версия пакета — 18.0, предназначенная для .NET 6, поэтому не подходит для приложений .NET Framework.
Вы устанавливаете Ocelot и его зависимости в проекте ASP.NET Core с пакетом NuGet Ocelot из Visual Studio.
Install-Package Ocelot
В eShopOnContainers реализация шлюза API — это простой проект ASP.NET Core WebHost, а ПО промежуточного слоя Ocelot обрабатывает все функции шлюза API, как показано на следующем рисунке:
Рис. 6-32. Базовый проект OcelotApiGw в eShopOnContainers
Этот проект ASP.NET Core WebHost построен с двумя простыми файлами: Program.cs
и Startup.cs
.
Program.cs просто необходимо создать и настроить типичный ASP.NET Core BuildWebHost.
namespace OcelotApiGw
{
public class Program
{
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args)
{
var builder = WebHost.CreateDefaultBuilder(args);
builder.ConfigureServices(s => s.AddSingleton(builder))
.ConfigureAppConfiguration(
ic => ic.AddJsonFile(Path.Combine("configuration",
"configuration.json")))
.UseStartup<Startup>();
var host = builder.Build();
return host;
}
}
}
Важной точкой здесь для Ocelot является configuration.json
файл, который необходимо предоставить построителю с помощью AddJsonFile()
метода. В этом configuration.json
случае вы указываете все reRoutes шлюза API, то есть внешние конечные точки с определенными портами и коррелированные внутренние конечные точки, обычно использующие разные порты.
{
"ReRoutes": [],
"GlobalConfiguration": {}
}
В конфигурации есть два раздела. Массив reRoutes и GlobalConfiguration. ReRoutes — это объекты, которые сообщают Ocelot, как обрабатывать вышестоящий запрос. Глобальная конфигурация позволяет переопределить определенные параметры ReRoute. Это полезно, если вы не хотите управлять большим количеством параметров ReRoute.
Ниже приведен упрощенный пример файла конфигурации ReRoute из одного из шлюзов API из eShopOnContainers.
{
"ReRoutes": [
{
"DownstreamPathTemplate": "/api/{version}/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "catalog-api",
"Port": 80
}
],
"UpstreamPathTemplate": "/api/{version}/c/{everything}",
"UpstreamHttpMethod": [ "POST", "PUT", "GET" ]
},
{
"DownstreamPathTemplate": "/api/{version}/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "basket-api",
"Port": 80
}
],
"UpstreamPathTemplate": "/api/{version}/b/{everything}",
"UpstreamHttpMethod": [ "POST", "PUT", "GET" ],
"AuthenticationOptions": {
"AuthenticationProviderKey": "IdentityApiKey",
"AllowedScopes": []
}
}
],
"GlobalConfiguration": {
"RequestIdKey": "OcRequestId",
"AdministrationPath": "/administration"
}
}
Основная функциональность шлюза API Ocelot заключается в том, чтобы принимать входящие HTTP-запросы и пересылать их в нижестоящей службе, в настоящее время в качестве другого HTTP-запроса. Ocelot описывает маршрутизацию одного запроса на другой как reRoute.
Например, давайте сосредоточимся на одном из reRoutes в configuration.json выше, конфигурации микрослужбы Корзины.
{
"DownstreamPathTemplate": "/api/{version}/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "basket-api",
"Port": 80
}
],
"UpstreamPathTemplate": "/api/{version}/b/{everything}",
"UpstreamHttpMethod": [ "POST", "PUT", "GET" ],
"AuthenticationOptions": {
"AuthenticationProviderKey": "IdentityApiKey",
"AllowedScopes": []
}
}
Подчиненный объектPathTemplate, Scheme и DownstreamHostAndPorts делают URL-адрес внутренней микрослужбы, в который будет перенаправляться этот запрос.
Порт — это внутренний порт, используемый службой. При использовании контейнеров порт, указанный в файле dockerfile.
Это Host
имя службы, зависящее от используемого разрешения имен службы. При использовании docker-compose имена служб предоставляются узлом Docker, который использует имена служб, указанные в файлах docker-compose. При использовании оркестратора, например Kubernetes или Service Fabric, это имя должно разрешаться разрешением DNS или имени, предоставленным каждым оркестратором.
DownstreamHostAndPorts — это массив, содержащий узел и порт всех подчиненных служб, в которые вы хотите пересылать запросы. Обычно эта конфигурация будет содержать только одну запись, но иногда может потребоваться балансировка нагрузки запросов к подчиненным службам и Ocelot позволяет добавить несколько записей, а затем выбрать подсистему балансировки нагрузки. Но если используется Azure и любой оркестратор, скорее всего, лучше использовать подсистему балансировки нагрузки с облачной инфраструктурой и инфраструктурой оркестратора.
UpstreamPathTemplate — это URL-адрес, который Ocelot будет использовать для определения того, какой из подчиненныхpathTemplate будет использоваться для заданного запроса от клиента. Наконец, upstreamHttpMethod используется, поэтому Ocelot может различать разные запросы (GET, POST, PUT) на один и тот же URL-адрес.
На этом этапе можно использовать один шлюз API Ocelot (ASP.NET Core WebHost) с помощью одного или нескольких объединенных configuration.json файлов или сохранить конфигурацию в хранилище Consul KV.
Но как описано в разделах архитектуры и проектирования, если вы действительно хотите иметь автономные микрослужбы, лучше разделить один монолитный шлюз API на несколько шлюзов API и /или BFF (серверная часть для frontend). Для этого давайте посмотрим, как реализовать этот подход с помощью контейнеров Docker.
Использование одного образа контейнера Docker для запуска нескольких различных типов контейнеров API и BFF
В eShopOnContainers мы используем один образ контейнера Docker с шлюзом API Ocelot, но во время выполнения мы создадим разные службы и контейнеры для каждого типа API-Gateway/BFF, предоставляя другой файл configuration.json, используя том Docker для доступа к другой папке ПК для каждой службы.
Рис. 6-33. Повторное использование одного образа Ocelot Docker в нескольких типах шлюзов API
В eShopOnContainers создается образ Docker шлюза Docker шлюза Ocelot API с именем OcelotApiGw и именем образа eshop/ocelotapigw, указанным в файле docker-compose.yml. Затем при развертывании в Docker будет четыре контейнера API-Gateway, созданные из этого же образа Docker, как показано в следующем извлечении из файла docker-compose.yml.
mobileshoppingapigw:
image: eshop/ocelotapigw:${TAG:-latest}
build:
context: .
dockerfile: src/ApiGateways/ApiGw-Base/Dockerfile
mobilemarketingapigw:
image: eshop/ocelotapigw:${TAG:-latest}
build:
context: .
dockerfile: src/ApiGateways/ApiGw-Base/Dockerfile
webshoppingapigw:
image: eshop/ocelotapigw:${TAG:-latest}
build:
context: .
dockerfile: src/ApiGateways/ApiGw-Base/Dockerfile
webmarketingapigw:
image: eshop/ocelotapigw:${TAG:-latest}
build:
context: .
dockerfile: src/ApiGateways/ApiGw-Base/Dockerfile
Кроме того, как можно увидеть в следующем docker-compose.override.yml файле, единственное различие между этими контейнерами шлюза API является файл конфигурации Ocelot, который отличается для каждого контейнера службы и указан во время выполнения через том Docker.
mobileshoppingapigw:
environment:
- ASPNETCORE_ENVIRONMENT=Development
- IdentityUrl=http://identity-api
ports:
- "5200:80"
volumes:
- ./src/ApiGateways/Mobile.Bff.Shopping/apigw:/app/configuration
mobilemarketingapigw:
environment:
- ASPNETCORE_ENVIRONMENT=Development
- IdentityUrl=http://identity-api
ports:
- "5201:80"
volumes:
- ./src/ApiGateways/Mobile.Bff.Marketing/apigw:/app/configuration
webshoppingapigw:
environment:
- ASPNETCORE_ENVIRONMENT=Development
- IdentityUrl=http://identity-api
ports:
- "5202:80"
volumes:
- ./src/ApiGateways/Web.Bff.Shopping/apigw:/app/configuration
webmarketingapigw:
environment:
- ASPNETCORE_ENVIRONMENT=Development
- IdentityUrl=http://identity-api
ports:
- "5203:80"
volumes:
- ./src/ApiGateways/Web.Bff.Marketing/apigw:/app/configuration
Из-за этого предыдущего кода и, как показано в приведенном ниже обозревателе Visual Studio, единственный файл, необходимый для определения каждого конкретного бизнес-шлюза ИЛИ BFF API— это всего лишь файл configuration.json, так как четыре шлюза API основаны на одном и том же образе Docker.
Рис. 6-34. Единственный файл, необходимый для определения каждого шлюза API или BFF с Ocelot, — это файл конфигурации.
Разделив шлюз API на несколько шлюзов API, различные группы разработчиков, ориентированные на различные подмножества микрослужб, могут управлять собственными шлюзами API с помощью независимых файлов конфигурации Ocelot. Кроме того, одновременно они могут повторно использовать тот же образ Ocelot Docker.
Теперь, если вы запускаете eShopOnContainers со шлюзами API (включенными по умолчанию в VS при открытии решения eShopOnContainers-ServicesAndWebApps.sln или при запуске docker-compose up), будут выполнены следующие примеры маршрутов.
Например, при посещении вышестоящего URL-адреса http://host.docker.internal:5202/api/v1/c/catalog/items/2/
, обслуживаемого шлюзом API webshoppingapigw, вы получаете тот же результат, что и внутренний URL-адрес http://catalog-api/api/v1/2
нижнего потока в узле Docker, как в следующем браузере.
Рис. 6–35. Доступ к микрослужбе через URL-адрес, предоставленный шлюзом API
Из-за тестирования или отладки, если вы хотите напрямую получить доступ к контейнеру Docker каталога (только в среде разработки) без передачи через шлюз API, так как "catalog-api" является разрешением DNS внутренним для узла Docker (обнаружение служб, обрабатываемых именами служб docker-compose), единственным способом прямого доступа к контейнеру является внешний порт, опубликованный в docker-compose.override.yml, предоставляется только для тестов разработки, таких как http://host.docker.internal:5101/api/v1/Catalog/items/1
в следующем браузере.
Рис. 6-36. Прямой доступ к микрослужбе для тестирования
Но приложение настроено таким образом, чтобы он обращается ко всем микрослужбам через шлюзы API, а не через прямой порт "ярлыки".
Шаблон агрегирования шлюза в eShopOnContainers
Как было представлено ранее, гибкий способ реализации агрегирования запросов — с пользовательскими службами по коду. Выбранный способ реализации агрегирования в eShopOnContainers является явным ASP.NET службой веб-API Core для каждого агрегатора.
В соответствии с этим подходом схема композиции шлюза API на самом деле более расширена при рассмотрении служб агрегатора, которые не отображаются на упрощенной схеме глобальной архитектуры, показанной ранее.
На следующей схеме также можно увидеть, как службы агрегатора работают со связанными шлюзами API.
Рис. 6–37. Архитектура eShopOnContainers со службами агрегатора
Увеличение масштаба в бизнес-области "Покупки" на следующем изображении можно увидеть, что чат между клиентскими приложениями и микрослужбами уменьшается при использовании служб агрегатора в шлюзах API.
Рис. 6–38. Увеличение масштаба служб агрегатора
Вы можете заметить, как на схеме отображаются возможные запросы, поступающие из шлюзов API, которые могут быть сложными. С другой стороны, при использовании шаблона агрегатора можно увидеть, как стрелки синим цветом упрощают обмен данными с точки зрения клиентского приложения. Этот шаблон не только помогает уменьшить количество чатов и задержку в взаимодействии, но и значительно улучшает взаимодействие пользователей для удаленных приложений (мобильных и SPA-приложений).
В случае с бизнес-областью "Маркетинг" и микрослужбами это простой вариант использования, поэтому не было необходимости использовать агрегаты, но это также может быть возможно при необходимости.
Проверка подлинности и авторизация в шлюзах API Ocelot
В шлюзе API Ocelot можно сидеть в службе проверки подлинности, например службе ASP.NET Core Web API с помощью IdentityServer , предоставляющей маркер проверки подлинности либо вне, либо внутри шлюза API.
Так как eShopOnContainers использует несколько шлюзов API с границами на основе BFF и бизнес-областей, служба Identity/Auth остается вне шлюзов API, как выделено желтым цветом на следующей схеме.
Рис. 6-39. Положение службы удостоверений в eShopOnContainers
Однако Ocelot также поддерживает сидящую микрослужбу Identity/Auth в пределах границы шлюза API, как и на этой другой схеме.
Рис. 6–40. Проверка подлинности в Ocelot
Как показано на предыдущей схеме, когда микрослужба удостоверений находится под шлюзом API (AG): 1) группа доступности запрашивает маркер проверки подлинности из микрослужбы удостоверений, 2) Микрослужба удостоверений возвращает маркер в группу доступности, 3-4) групп доступности запросов от микрослужб с помощью маркера проверки подлинности. Так как приложение eShopOnContainers разбило шлюз API на несколько BFF (серверная часть для внешнего интерфейса) и шлюзы API бизнес-областей, другой вариант — создать дополнительный шлюз API для перекрестных проблем. Этот выбор будет справедливым в более сложной архитектуре на основе микрослужб с несколькими перекрестными проблемами микрослужб. Так как в eShopOnContainers существует только одна перекрестная озабоченность, было решено просто обработать службу безопасности из области шлюза API, для простоты.
В любом случае, если приложение защищено на уровне шлюза API, модуль проверки подлинности шлюза API Ocelot сначала посещается при попытке использовать любую безопасную микрослужбу. Это перенаправляет HTTP-запрос, чтобы посетить микрослужбу Identity или auth, чтобы получить маркер доступа, чтобы вы могли посетить защищенные службы с помощью access_token.
Способ защиты с помощью проверки подлинности любой службы на уровне шлюза API заключается в настройке AuthenticationProviderKey в связанных параметрах на configuration.json.
{
"DownstreamPathTemplate": "/api/{version}/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "basket-api",
"Port": 80
}
],
"UpstreamPathTemplate": "/api/{version}/b/{everything}",
"UpstreamHttpMethod": [],
"AuthenticationOptions": {
"AuthenticationProviderKey": "IdentityApiKey",
"AllowedScopes": []
}
}
При запуске Ocelot он будет смотреть на ReRoutes AuthenticationOptions.AuthenticationProviderKey и проверить наличие поставщика проверки подлинности, зарегистрированного с заданным ключом. Если нет, то Ocelot не запустится. Если есть, reRoute будет использовать этот поставщик при выполнении.
Так как веб-сайт Ocelot настроен с помощью < a0
namespace OcelotApiGw
{
public class Startup
{
private readonly IConfiguration _cfg;
public Startup(IConfiguration configuration) => _cfg = configuration;
public void ConfigureServices(IServiceCollection services)
{
var identityUrl = _cfg.GetValue<string>("IdentityUrl");
var authenticationProviderKey = "IdentityApiKey";
//…
services.AddAuthentication()
.AddJwtBearer(authenticationProviderKey, x =>
{
x.Authority = identityUrl;
x.RequireHttpsMetadata = false;
x.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters()
{
ValidAudiences = new[] { "orders", "basket", "locations", "marketing", "mobileshoppingagg", "webshoppingagg" }
};
});
//...
}
}
}
Затем необходимо также задать авторизацию с атрибутом [Авторизовать] для любого ресурса, доступ к которым будет осуществляться как к микрослужбам, например в следующем контроллере микрослужб корзины.
namespace Microsoft.eShopOnContainers.Services.Basket.API.Controllers
{
[Route("api/v1/[controller]")]
[Authorize]
public class BasketController : Controller
{
//...
}
}
Допустимыеaudiences, такие как "корзина", коррелируются с аудиторией, определенной в каждой микрослужбе с AddJwtBearer()
параметром ConfigureServices() класса Startup, например в приведенном ниже коде.
// prevent from mapping "sub" claim to nameidentifier.
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
var identityUrl = Configuration.GetValue<string>("IdentityUrl");
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
options.Authority = identityUrl;
options.RequireHttpsMetadata = false;
options.Audience = "basket";
});
Если вы пытаетесь получить доступ к любой защищенной микрослужбе, например микрослужбе Корзины с URL-адресом ReRoute на основе шлюза API, например http://host.docker.internal:5202/api/v1/b/basket/1
, вы получите 401 Неавторизованный, если вы не предоставили действительный маркер. С другой стороны, если URL-адрес ReRoute проходит проверку подлинности, Ocelot вызовет любую нижестоящей схему, связанную с ней (URL-адрес внутренней микрослужбы).
Авторизация на уровне ReRoutes Ocelot. Ocelot поддерживает авторизацию на основе утверждений, вычисляемую после проверки подлинности. Чтобы настроить авторизацию на уровне маршрута, добавьте следующие строки в конфигурацию ReRoute.
"RouteClaimsRequirement": {
"UserType": "employee"
}
В этом примере при вызове по промежуточного слоя авторизации Ocelot обнаружит, имеет ли пользователь тип утверждения UserType в токене, а значение этого утверждения — employee. Если это не так, пользователь не будет авторизован, и ответ будет запрещен 403.
Использование входящего трафика Kubernetes и шлюзов API Ocelot
При использовании Kubernetes (например, в кластере службы Azure Kubernetes) обычно вы объединяете все HTTP-запросы через уровень входящего трафика Kubernetes на основе Nginx.
В Kubernetes, если вы не используете любой подход к входящего трафика, то службы и модули pod имеют ip-адреса, доступные только для routable в сети кластера.
Но если вы используете подход входящего трафика, вы будете иметь средний уровень между Интернетом и службами (включая шлюзы API), выступая в качестве обратного прокси-сервера.
Как определение, входящий трафик представляет собой коллекцию правил, которые позволяют входящего трафика подключаться к службам кластера. Входящий трафик настраивается для предоставления служб внешних доступных URL-адресов, балансировки нагрузки трафика, завершения SSL и т. д. Пользователи запрашивают входящий трафик, позируя ресурс входящего трафика на сервер API.
В eShopOnContainers при локальной разработке и использовании только компьютера разработки в качестве узла Docker вы не используете ни одного входящего трафика, но только нескольких шлюзов API.
Однако при выборе рабочей среды на основе Kubernetes eShopOnContainers используется входящий трафик перед шлюзами API. Таким образом, клиенты по-прежнему вызывают один и тот же базовый URL-адрес, но запросы направляются в несколько шлюзов API или BFF.
Шлюзы API являются интерфейсными или фасадами, отображающими только службы, но не веб-приложения, которые обычно находятся вне их области. Кроме того, шлюзы API могут скрывать определенные внутренние микрослужбы.
Однако входящий трафик просто перенаправляет HTTP-запросы, но не пытается скрыть микрослужбу или веб-приложение.
Наличие уровня ingress Nginx в Kubernetes перед веб-приложениями, а также несколько шлюзов API Ocelot / BFF является идеальной архитектурой, как показано на следующей схеме.
Рис. 6–41. Уровень входящего трафика в eShopOnContainers при развертывании в Kubernetes
Kubernetes Ingress выступает в качестве обратного прокси-сервера для всего трафика в приложение, включая веб-приложения, которые находятся вне области шлюза API. При развертывании eShopOnContainers в Kubernetes он предоставляет только несколько служб или конечных точек через входящий трафик, в основном следующий список постфиксов на URL-адресах:
-
/
для веб-приложения SPA клиента -
/webmvc
для веб-приложения MVC клиента -
/webstatus
для клиентского веб-приложения с проверками состояния и работоспособности -
/webshoppingapigw
для веб-бизнес-процессов BFF и покупок -
/webmarketingapigw
для веб-бизнес-процессов BFF и маркетинга -
/mobileshoppingapigw
для мобильных бизнес-процессов BFF и покупок -
/mobilemarketingapigw
для мобильных бизнес-процессов BFF и маркетинга
При развертывании в Kubernetes каждый шлюз API Ocelot использует другой файл "configuration.json" для каждого модуля pod под управлением шлюзов API. Эти файлы "configuration.json" предоставляются подключением (первоначально с помощью скрипта deploy.ps1) тома, созданного на основе карты конфигурации Kubernetes с именем Ocelot. Каждый контейнер подключает соответствующий файл конфигурации в папке контейнера с именем /app/configuration
.
В файлах исходного кода eShopOnContainers исходные файлы "configuration.json" можно найти в папке k8s/ocelot/
. Существует один файл для каждого BFF/APIGateway.
Дополнительные возможности перекрестной работы в шлюзе API Ocelot
При использовании шлюза API Ocelot существуют и другие важные функции, описанные в следующих ссылках.
Обнаружение служб на стороне клиента, интегрирующее Ocelot с Consul или Eureka
https://ocelot.readthedocs.io/en/latest/features/servicediscovery.htmlКэширование на уровне шлюза API
https://ocelot.readthedocs.io/en/latest/features/caching.htmlВедение журнала на уровне шлюза API
https://ocelot.readthedocs.io/en/latest/features/logging.htmlКачество обслуживания (повторные попытки и разбиения каналов) на уровне шлюза API
https://ocelot.readthedocs.io/en/latest/features/qualityofservice.htmlОграничение частоты
https://ocelot.readthedocs.io/en/latest/features/ratelimiting.htmlSwagger для Ocelot
https://github.com/Burgyn/MMLib.SwaggerForOcelot