Notes
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Conseil / Astuce
Ce contenu est un extrait du livre .NET Microservices Architecture for Containerized .NET Applications, disponible sur .NET Docs ou en tant que PDF téléchargeable gratuitement pour une lecture hors ligne.
Importante
L’application de microservice de référence eShopOnContainers utilise actuellement des fonctionnalités fournies par Envoy pour implémenter la passerelle API au lieu de l’Ocelot référencé précédemment. Nous avons fait ce choix de conception en raison de la prise en charge intégrée de Envoy pour le protocole WebSocket, requis par les nouvelles communications interservices gRPC implémentées dans eShopOnContainers. Toutefois, nous avons conservé cette section dans le guide afin de pouvoir considérer Ocelot comme une passerelle API simple, capable et légère adaptée aux scénarios de niveau production. En outre, la dernière version d’Ocelot contient une modification cassante sur son schéma json. Envisagez d’utiliser Ocelot < v16.0.0 ou utilisez les itinéraires clés au lieu de ReRoutes.
Architecture et conception de vos passerelles d’API
Le diagramme d’architecture suivant montre comment les passerelles API ont été implémentées avec Ocelot dans eShopOnContainers.
Figure 6-28. Architecture eShopOnContainers avec des passerelles d’API
Ce diagramme montre comment l’application entière est déployée dans un seul ordinateur hôte Docker ou pc de développement avec « Docker pour Windows » ou « Docker pour Mac ». Toutefois, le déploiement dans n’importe quel orchestrateur serait similaire, mais tout conteneur du diagramme peut être mis à l’échelle dans l’orchestrateur.
En outre, les ressources d’infrastructure telles que les bases de données, le cache et les répartiteurs de messages doivent être déchargées de l’orchestrateur et déployées dans des systèmes à haute disponibilité pour l’infrastructure, comme Azure SQL Database, Azure Cosmos DB, Azure Redis, Azure Service Bus ou toute solution de clustering haute disponibilité locale.
Comme vous pouvez également le constater dans le diagramme, la présence de plusieurs passerelles d’API permet à plusieurs équipes de développement d’être autonomes (dans ce cas, fonctionnalités marketing et fonctionnalités d’achat) lors du développement et du déploiement de leurs microservices et de leurs propres passerelles d’API associées.
Si vous aviez une passerelle API monolithique unique qui signifierait qu’un point unique doit être mis à jour par plusieurs équipes de développement, ce qui peut coupler tous les microservices avec une seule partie de l’application.
Aller beaucoup plus loin dans la conception, parfois une passerelle d’API affinée peut également être limitée à un seul microservice métier en fonction de l’architecture choisie. Le fait d’avoir les limites de la passerelle d’API dictées par l’entreprise ou le domaine vous aidera à obtenir une meilleure conception.
Par exemple, une granularité précise dans le niveau passerelle d’API peut être particulièrement utile pour les applications d’interface utilisateur composites plus avancées basées sur des microservices, car le concept d’une passerelle d’API affinée est similaire à un service de composition d’interface utilisateur.
Nous allons examiner plus en détail dans la section précédente La création d’une interface utilisateur composite basée sur les microservices.
En guise de prise en compte clé, pour de nombreuses applications de taille moyenne et grande, l’utilisation d’un produit de passerelle d’API personnalisé est généralement une bonne approche, mais pas comme un agrégateur monolithique unique ou une passerelle API personnalisée centrale unique, sauf si cette passerelle API autorise plusieurs zones de configuration indépendantes pour les équipes de développement créant des microservices autonomes.
Exemples de microservices/conteneurs à rediriger via les passerelles d’API
Par exemple, eShopOnContainers a environ six types de microservice internes qui doivent être publiés via les passerelles d’API, comme illustré dans l’image suivante.
Figure 6-29. Dossiers de microservice dans la solution eShopOnContainers dans Visual Studio
À propos du service Identity, dans la conception, il est laissé hors du routage de la passerelle API, car il s’agit de la seule préoccupation croisée dans le système, bien qu’avec Ocelot, il est également possible de l’inclure dans le cadre des listes de réacheminement.
Tous ces services sont actuellement implémentés en tant que services d’API web core ASP.NET, comme vous pouvez le savoir à partir du code. Nous allons nous concentrer sur l’un des microservices comme le code du microservice Catalog.
Figure 6-30. Exemple de microservice d’API web (microservice catalogue)
Vous pouvez voir que le microservice Catalog est un projet d’API web standard ASP.NET Core avec plusieurs contrôleurs et méthodes comme dans le code suivant.
[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();
}
La requête HTTP finira par exécuter ce type de code C# qui accède à la base de données de microservice et toute action supplémentaire requise.
Concernant l’URL du microservice, lorsque les conteneurs sont déployés dans votre PC de développement local (hôte Docker local), le conteneur de chaque microservice a toujours un port interne (généralement le port 80) spécifié dans son fichier dockerfile, comme dans le fichier dockerfile suivant :
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
WORKDIR /app
EXPOSE 80
Le port 80 indiqué dans le code est interne au sein de l’hôte Docker. Il ne peut donc pas être atteint par les applications clientes.
Les applications clientes peuvent accéder uniquement aux ports externes (le cas échéant) publiés lors du déploiement avec docker-compose
.
Ces ports externes ne doivent pas être publiés lors du déploiement dans un environnement de production. Pour cette raison spécifique, pourquoi vous souhaitez utiliser la passerelle API pour éviter la communication directe entre les applications clientes et les microservices.
Toutefois, lors du développement, vous souhaitez accéder directement au microservice/conteneur et l’exécuter via Swagger. C’est pourquoi dans eShopOnContainers, les ports externes sont toujours spécifiés même quand ils ne seront pas utilisés par la passerelle API ou les applications clientes.
Voici un exemple de docker-compose.override.yml
fichier pour le microservice Catalog :
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).
Vous pouvez voir comment dans la configuration docker-compose.override.yml le port interne du conteneur catalogue est le port 80, mais le port pour l’accès externe est 5101. Toutefois, ce port ne doit pas être utilisé par l’application lors de l’utilisation d’une passerelle API, uniquement pour déboguer, exécuter et tester uniquement le microservice Catalog.
Normalement, vous ne déployez pas docker-compose dans un environnement de production, car le bon environnement de déploiement de production pour les microservices est un orchestrateur comme Kubernetes ou Service Fabric. Lors du déploiement sur ces environnements, vous utilisez différents fichiers de configuration où vous ne publierez pas directement de port externe pour les microservices, mais vous utiliserez toujours le proxy inverse à partir de la passerelle API.
Exécutez le microservice catalogue dans votre hôte Docker local. Exécutez la solution eShopOnContainers complète à partir de Visual Studio (elle exécute tous les services dans les fichiers docker-compose), ou démarrez le microservice Catalog avec la commande docker-compose suivante dans CMD ou PowerShell positionnée sur le dossier où le docker-compose.yml
fichier et docker-compose.override.yml
sont placés.
docker-compose run --service-ports catalog-api
Cette commande exécute uniquement le conteneur de service catalog-api ainsi que les dépendances spécifiées dans le docker-compose.yml. Dans ce cas, le conteneur SQL Server et le conteneur RabbitMQ.
Ensuite, vous pouvez accéder directement au microservice Catalog et voir ses méthodes via l’interface utilisateur Swagger qui accède directement via ce port « externe », dans ce cas http://host.docker.internal:5101/swagger
:
Figure 6-31. Test du microservice catalogue avec son interface utilisateur Swagger
À ce stade, vous pouvez définir un point d’arrêt dans le code C# dans Visual Studio, tester le microservice avec les méthodes exposées dans l’interface utilisateur Swagger, et enfin nettoyer tout avec la docker-compose down
commande.
Toutefois, la communication directe avec le microservice, dans ce cas via le port externe 5101, est précisément ce que vous souhaitez éviter dans votre application. Et vous pouvez éviter cela en définissant le niveau supplémentaire d’indirection de la passerelle API (Ocelot, dans ce cas). De cette façon, l’application cliente n’accède pas directement au microservice.
Implémentation de vos passerelles d’API avec Ocelot
Ocelot est essentiellement un ensemble d’intergiciels que vous pouvez appliquer dans un ordre spécifique.
Ocelot est conçu pour fonctionner avec ASP.NET Core uniquement. La dernière version du package est 18.0 qui cible .NET 6 et n’est donc pas adaptée aux applications .NET Framework.
Vous installez Ocelot et ses dépendances dans votre projet ASP.NET Core avec le package NuGet d’Ocelot, à partir de Visual Studio.
Install-Package Ocelot
Dans eShopOnContainers, son implémentation de passerelle d’API est une simple ASP.NET projet Core WebHost et l’intergiciel Ocelot gère toutes les fonctionnalités de passerelle d’API, comme illustré dans l’image suivante :
Figure 6-32. Le projet de base OcelotApiGw dans eShopOnContainers
Ce projet ASP.NET Core WebHost est généré avec deux fichiers simples : Program.cs
et Startup.cs
.
Le Program.cs doit simplement créer et configurer le ASP.NET Core BuildWebHost standard.
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;
}
}
}
Le point important ici pour Ocelot est le configuration.json
fichier que vous devez fournir au générateur via la AddJsonFile()
méthode. C’est là que configuration.json
vous spécifiez tous les réroutes de passerelle d’API, ce qui signifie que les points de terminaison externes avec des ports spécifiques et les points de terminaison internes corrélés utilisent généralement des ports différents.
{
"ReRoutes": [],
"GlobalConfiguration": {}
}
Il existe deux sections de la configuration. Tableau de ReRoutes et d’une GlobalConfiguration. Les ReRoutes sont les objets qui indiquent à Ocelot comment traiter une requête en amont. La configuration globale autorise les remplacements de paramètres spécifiques à ReRoute. Il est utile si vous ne souhaitez pas gérer un grand nombre de paramètres spécifiques à ReRoute.
Voici un exemple simplifié de fichier de configuration ReRoute à partir de l’une des passerelles API d’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"
}
}
La fonctionnalité principale d’une passerelle d’API Ocelot consiste à prendre des requêtes HTTP entrantes et à les transférer vers un service en aval, actuellement en tant que autre requête HTTP. Ocelot décrit le routage d’une requête vers une autre en tant que ReRoute.
Par exemple, nous allons nous concentrer sur l’un des ReRoutes de la configuration.json ci-dessus, la configuration du microservice Basket.
{
"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": []
}
}
Le paramètre DownstreamPathTemplate, Scheme et DownstreamHostAndPorts rendent l’URL de microservice interne à laquelle cette requête sera transférée.
Le port est le port interne utilisé par le service. Lors de l’utilisation de conteneurs, le port spécifié à son fichier dockerfile.
Il Host
s’agit d’un nom de service qui dépend de la résolution de noms de service que vous utilisez. Lorsque vous utilisez docker-compose, les noms de services sont fournis par l’hôte Docker, qui utilise les noms de service fournis dans les fichiers docker-compose. Si vous utilisez un orchestrateur comme Kubernetes ou Service Fabric, ce nom doit être résolu par le DNS ou la résolution de noms fournie par chaque orchestrateur.
DownstreamHostAndPorts est un tableau qui contient l’hôte et le port de tous les services en aval auxquels vous souhaitez transférer des requêtes. En règle générale, cette configuration contient simplement une entrée, mais parfois vous souhaiterez peut-être équilibrer la charge des demandes adressées à vos services en aval et Ocelot vous permet d’ajouter plusieurs entrées, puis de sélectionner un équilibreur de charge. Mais si vous utilisez Azure et n’importe quel orchestrateur, il est probablement préférable d’équilibrer la charge avec l’infrastructure cloud et orchestrator.
L’Élément UpstreamPathTemplate est l’URL que Ocelot utilisera pour identifier le paramètre DownstreamPathTemplate à utiliser pour une requête donnée du client. Enfin, l’élément UpstreamHttpMethod est utilisé afin que Ocelot puisse faire la distinction entre différentes requêtes (GET, POST, PUT) vers la même URL.
À ce stade, vous pouvez avoir une seule passerelle d’API Ocelot (ASP.NET Core WebHost) à l’aide d’un ou plusieurs fichiers fusionnés configuration.json , ou vous pouvez également stocker la configuration dans un magasin Consul KV.
Mais comme introduit dans les sections architecture et conception, si vous souhaitez vraiment avoir des microservices autonomes, il peut être préférable de fractionner cette passerelle API monolithique unique en plusieurs passerelles API et/ou BFF (back-end pour front-end). À cet effet, voyons comment implémenter cette approche avec des conteneurs Docker.
Utilisation d’une seule image conteneur Docker pour exécuter plusieurs types de conteneurs API Gateway / BFF différents
Dans eShopOnContainers, nous utilisons une seule image conteneur Docker avec la passerelle API Ocelot, mais ensuite, au moment de l’exécution, nous créons différents services/conteneurs pour chaque type de passerelle API-Gateway/BFF en fournissant un fichier configuration.json différent, à l’aide d’un volume Docker pour accéder à un dossier PC différent pour chaque service.
Figure 6-33. Réutilisation d’une seule image Docker Ocelot sur plusieurs types de passerelle d’API
Dans eShopOnContainers, l'« image Docker de la passerelle API Ocelot générique » est créée avec le projet nommé « OcelotApiGw » et le nom d’image « eshop/ocelotapigw » spécifié dans le fichier docker-compose.yml. Ensuite, lors du déploiement sur Docker, il y aura quatre conteneurs API-Gateway créés à partir de cette même image Docker, comme indiqué dans l’extrait suivant du fichier 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
En outre, comme vous pouvez le voir dans le fichier docker-compose.override.yml suivant, la seule différence entre ces conteneurs de passerelle d’API est le fichier de configuration Ocelot, qui est différent pour chaque conteneur de service et il est spécifié au moment de l’exécution via un volume 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
En raison de ce code précédent, et comme indiqué dans l’Explorateur Visual Studio ci-dessous, le seul fichier nécessaire pour définir chaque passerelle d’API BFF/métier spécifique n’est qu’un fichier configuration.json, car les quatre passerelles d’API sont basées sur la même image Docker.
Figure 6-34. Le seul fichier nécessaire pour définir chaque passerelle API / BFF avec Ocelot est un fichier de configuration
En fractionnant la passerelle API en plusieurs passerelles API, différentes équipes de développement se concentrant sur différents sous-ensembles de microservices peuvent gérer leurs propres passerelles API à l’aide de fichiers de configuration Ocelot indépendants. De plus, en même temps, ils peuvent réutiliser la même image Docker Ocelot.
À présent, si vous exécutez eShopOnContainers avec les passerelles d’API (incluses par défaut dans VS lors de l’ouverture de la solution eShopOnContainers-ServicesAndWebApps.sln ou si vous exécutez « docker-compose up »), les exemples d’itinéraires suivants sont effectués.
Par exemple, lors de la visite de l’URL http://host.docker.internal:5202/api/v1/c/catalog/items/2/
en amont fournie par la passerelle d’API Webshoppingapigw, vous obtenez le même résultat à partir de l’URL http://catalog-api/api/v1/2
en aval interne au sein de l’hôte Docker, comme dans le navigateur suivant.
Figure 6-35. Accès à un microservice via une URL fournie par la passerelle d’API
Pour des raisons de test ou de débogage, si vous souhaitez accéder directement au conteneur Docker catalogue (uniquement dans l’environnement de développement) sans passer par la passerelle d’API, étant donné que « catalog-api » est une résolution DNS interne à l’hôte Docker (découverte de service gérée par les noms de service docker-compose), la seule façon d’accéder directement au conteneur est via le port externe publié dans l’docker-compose.override.yml, qui est fourni uniquement pour les tests de développement, comme http://host.docker.internal:5101/api/v1/Catalog/items/1
dans le navigateur suivant.
Figure 6-36. Accès direct à un microservice à des fins de test
Mais l’application est configurée afin qu’elle accède à tous les microservices via les passerelles d’API, et non pas via les « raccourcis » du port direct.
Modèle d’agrégation de passerelle dans eShopOnContainers
Comme introduit précédemment, un moyen flexible d’implémenter l’agrégation des requêtes est avec des services personnalisés, par code. La méthode sélectionnée pour implémenter l’agrégation dans eShopOnContainers est avec un service d’API web core ASP.NET explicite pour chaque agrégateur.
Selon cette approche, le diagramme de composition de la passerelle d’API est en réalité un peu plus étendu lorsque vous envisagez les services d’agrégation qui ne sont pas affichés dans le diagramme d’architecture globale simplifié présenté précédemment.
Dans le diagramme suivant, vous pouvez également voir comment les services d’agrégation fonctionnent avec leurs passerelles d’API associées.
Figure 6-37. Architecture eShopOnContainers avec les services d’agrégation
Zoomez plus loin, sur la zone métier « Shopping » dans l’image suivante, vous pouvez voir que les conversations entre les applications clientes et les microservices sont réduites lors de l’utilisation des services d’agrégation dans les passerelles d’API.
Figure 6-38. Zoom avant vision des services Aggregator
Vous pouvez remarquer comment quand le diagramme affiche les requêtes possibles provenant des passerelles API, il peut être complexe. En revanche, lorsque vous utilisez le modèle d’agrégation, vous pouvez voir comment les flèches en bleu simplifient la communication du point de vue de l’application cliente. Ce modèle permet non seulement de réduire les conversations et la latence dans la communication, mais également d’améliorer considérablement l’expérience utilisateur pour les applications distantes (applications mobiles et SPA).
Dans le cas des microservices et de la zone commerciale « Marketing », il s’agit d’un cas d’usage simple afin qu’il n’y ait pas besoin d’utiliser des agrégateurs, mais il pourrait également être possible, si nécessaire.
Authentification et autorisation dans les passerelles d’API Ocelot
Dans une passerelle d’API Ocelot, vous pouvez asseoir le service d’authentification, tel qu’un service d’API web ASP.NET Core à l’aide de IdentityServer fournissant le jeton d’authentification, soit à l’intérieur de la passerelle d’API.
Étant donné que eShopOnContainers utilise plusieurs passerelles d’API avec des limites basées sur les zones BFF et métier, le service Identity/Auth est laissé hors des passerelles d’API, comme mis en surbrillance en jaune dans le diagramme suivant.
Figure 6-39. Position du service Identity dans eShopOnContainers
Toutefois, Ocelot prend également en charge le microservice Identity/Auth au sein de la limite de la passerelle API, comme dans cet autre diagramme.
Figure 6-40. Authentification dans Ocelot
Comme le montre le diagramme précédent, lorsque le microservice Identity se trouve sous la passerelle d’API (AG) : 1) le groupe de disponibilité demande un jeton d’authentification à partir du microservice d’identité, 2) Le microservice d’identité retourne le jeton au groupe de disponibilité, 3 à 4) demandes de groupe de disponibilité des microservices à l’aide du jeton d’authentification. Étant donné que l’application eShopOnContainers a divisé la passerelle d’API en plusieurs passerelles BFF (backend pour frontend) et les passerelles API des zones métier, une autre option aurait été de créer une passerelle d’API supplémentaire pour des préoccupations croisées. Ce choix serait équitable dans une architecture basée sur des microservices plus complexes avec plusieurs microservices inter-coupes. Étant donné qu’il n’y a qu’une seule préoccupation croisée dans eShopOnContainers, il a été décidé de gérer simplement le service de sécurité hors du domaine de la passerelle API, par souci de simplicité.
Dans tous les cas, si l’application est sécurisée au niveau de la passerelle API, le module d’authentification de la passerelle d’API Ocelot est visité au début lors de la tentative d’utilisation d’un microservice sécurisé. Vous redirigez la requête HTTP pour visiter le microservice Identity ou auth pour obtenir le jeton d’accès afin de pouvoir visiter les services protégés avec le access_token.
La façon dont vous sécurisez avec l’authentification n’importe quel service au niveau de la passerelle d’API consiste à définir AuthenticationProviderKey dans ses paramètres associés à l'configuration.json.
{
"DownstreamPathTemplate": "/api/{version}/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "basket-api",
"Port": 80
}
],
"UpstreamPathTemplate": "/api/{version}/b/{everything}",
"UpstreamHttpMethod": [],
"AuthenticationOptions": {
"AuthenticationProviderKey": "IdentityApiKey",
"AllowedScopes": []
}
}
Quand Ocelot s’exécute, il examine reRoutes AuthenticationOptions.AuthenticationProviderKey et vérifie qu’il existe un fournisseur d’authentification inscrit avec la clé donnée. Si ce n’est pas le cas, Ocelot ne démarre pas. S’il en existe, le reRoute utilise ce fournisseur lorsqu’il s’exécute.
Étant donné que l’Ocelot WebHost est configuré avec le authenticationProviderKey = "IdentityApiKey"
, qui nécessite une authentification chaque fois que ce service a des demandes sans jeton d’authentification.
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" }
};
});
//...
}
}
}
Ensuite, vous devez également définir l’autorisation avec l’attribut [Authorize] sur n’importe quelle ressource à accéder comme les microservices, comme dans le contrôleur de microservice Basket suivant.
namespace Microsoft.eShopOnContainers.Services.Basket.API.Controllers
{
[Route("api/v1/[controller]")]
[Authorize]
public class BasketController : Controller
{
//...
}
}
Les ValidAudiences telles que « panier » sont corrélées avec l’audience définie dans chaque microservice avec AddJwtBearer()
au niveau de la classe ConfigureServices() de la classe Startup, comme dans le code ci-dessous.
// 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";
});
Si vous essayez d’accéder à n’importe quel microservice sécurisé, comme le microservice Basket avec une URL ReRoute basée sur la passerelle d’API, par exemple http://host.docker.internal:5202/api/v1/b/basket/1
, vous obtiendrez un 401 Non autorisé, sauf si vous fournissez un jeton valide. En revanche, si une URL ReRoute est authentifiée, Ocelot appelle le schéma en aval associé à celui-ci (l’URL du microservice interne).
Autorisation au niveau ReRoutes d’Ocelot. Ocelot prend en charge l’autorisation basée sur les revendications évaluée après l’authentification. Vous définissez l’autorisation au niveau de l’itinéraire en ajoutant les lignes suivantes à la configuration ReRoute.
"RouteClaimsRequirement": {
"UserType": "employee"
}
Dans cet exemple, lorsque l’intergiciel d’autorisation est appelé, Ocelot recherche si l’utilisateur a le type de revendication « UserType » dans le jeton et si la valeur de cette revendication est « employee ». Si ce n’est pas le cas, l’utilisateur ne sera pas autorisé et la réponse sera 403 interdite.
Utilisation de Kubernetes Ingress et de passerelles d’API Ocelot
Lorsque vous utilisez Kubernetes (comme dans un cluster Azure Kubernetes Service), vous unifiez généralement toutes les requêtes HTTP via le niveau d’entrée Kubernetes basé sur Nginx.
Dans Kubernetes, si vous n’utilisez aucune approche d’entrée, vos services et pods ont uniquement des adresses IP routables par le réseau de cluster.
Toutefois, si vous utilisez une approche d’entrée, vous disposez d’un niveau intermédiaire entre Internet et vos services (y compris vos passerelles API), agissant en tant que proxy inverse.
En guise de définition, une entrée est une collection de règles qui permettent aux connexions entrantes d’atteindre les services de cluster. Une entrée est configurée pour fournir des URL accessibles en externe, équilibrer la charge du trafic, l’arrêt SSL et bien plus encore. Les utilisateurs demandent l’entrée par POSTing de la ressource d’entrée sur le serveur d’API.
Dans eShopOnContainers, lors du développement localement et en utilisant uniquement votre ordinateur de développement en tant qu’hôte Docker, vous n’utilisez pas d’entrée, mais uniquement les passerelles d’API multiples.
Toutefois, lors du ciblage d’un environnement de « production » basé sur Kubernetes, eShopOnContainers utilise une entrée devant les passerelles d’API. Ainsi, les clients appellent toujours la même URL de base, mais les requêtes sont acheminées vers plusieurs passerelles d’API ou BFF.
Les passerelles API sont des front-ends ou des façades qui font face uniquement aux services, mais pas aux applications web qui sont généralement hors de leur portée. En outre, les passerelles d’API peuvent masquer certains microservices internes.
Toutefois, l’entrée consiste simplement à rediriger les requêtes HTTP, mais à ne pas essayer de masquer n’importe quel microservice ou application web.
Avoir un niveau Nginx d’entrée dans Kubernetes devant les applications web, ainsi que plusieurs passerelles d’API Ocelot / BFF est l’architecture idéale, comme illustré dans le diagramme suivant.
Figure 6-41. Niveau d’entrée dans eShopOnContainers lors du déploiement dans Kubernetes
Une entrée Kubernetes agit comme un proxy inverse pour tout le trafic vers l’application, y compris les applications web, qui sont hors de l’étendue de la passerelle Api. Lorsque vous déployez eShopOnContainers dans Kubernetes, il expose seulement quelques services ou points de terminaison via l’entrée, en gros la liste suivante de postfixes sur les URL :
-
/
pour l’application web SPA cliente -
/webmvc
pour l’application web MVC cliente -
/webstatus
pour l’application web cliente montrant l’état/les vérifications d’intégrité -
/webshoppingapigw
pour le web BFF et les processus métier d’achat -
/webmarketingapigw
pour les processus métier web BFF et marketing -
/mobileshoppingapigw
pour le BFF mobile et les processus métier d’achat -
/mobilemarketingapigw
pour les processus métier mobiles BFF et marketing
Lors du déploiement sur Kubernetes, chaque passerelle d’API Ocelot utilise un fichier «configuration.json» différent pour chaque pod exécutant les passerelles d’API. Ces fichiers «configuration.json» sont fournis en montage (à l’origine avec le script deploy.ps1) un volume créé en fonction d’une carte de configuration Kubernetes nommée « ocelot ». Chaque conteneur monte son fichier de configuration associé dans le dossier du conteneur nommé /app/configuration
.
Dans les fichiers de code source d’eShopOnContainers, les fichiers «configuration.json» d’origine se trouvent dans le k8s/ocelot/
dossier. Il existe un fichier pour chaque BFF/APIGateway.
Fonctionnalités croisées supplémentaires dans une passerelle d’API Ocelot
Il existe d’autres fonctionnalités importantes à rechercher et à utiliser, lors de l’utilisation d’une passerelle d’API Ocelot, décrites dans les liens suivants.
Découverte de services côté client intégrant Ocelot avec Consul ou Eureka
https://ocelot.readthedocs.io/en/latest/features/servicediscovery.htmlMise en cache au niveau de la passerelle d’API
https://ocelot.readthedocs.io/en/latest/features/caching.htmlJournalisation au niveau de la passerelle d’API
https://ocelot.readthedocs.io/en/latest/features/logging.htmlQualité de service (nouvelles tentatives et disjoncteurs) au niveau de la passerelle API
https://ocelot.readthedocs.io/en/latest/features/qualityofservice.htmlLimitation du débit
https://ocelot.readthedocs.io/en/latest/features/ratelimiting.htmlSwagger pour Ocelot
https://github.com/Burgyn/MMLib.SwaggerForOcelot